aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets/test')
-rw-r--r--lib/inets/test/Makefile29
-rw-r--r--lib/inets/test/erl_make_certs.erl429
-rw-r--r--lib/inets/test/ftp_SUITE.erl843
-rw-r--r--lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel14
-rw-r--r--lib/inets/test/ftp_SUITE_data/vsftpd.conf26
-rw-r--r--lib/inets/test/ftp_format_SUITE.erl2
-rw-r--r--lib/inets/test/ftp_freebsd_x86_test.erl160
-rw-r--r--lib/inets/test/ftp_linux_ppc_test.erl158
-rw-r--r--lib/inets/test/ftp_linux_x86_test.erl160
-rw-r--r--lib/inets/test/ftp_macosx_ppc_test.erl159
-rw-r--r--lib/inets/test/ftp_macosx_x86_test.erl159
-rw-r--r--lib/inets/test/ftp_netbsd_x86_test.erl159
-rw-r--r--lib/inets/test/ftp_openbsd_x86_test.erl158
-rw-r--r--lib/inets/test/ftp_solaris10_sparc_test.erl161
-rw-r--r--lib/inets/test/ftp_solaris10_x86_test.erl162
-rw-r--r--lib/inets/test/ftp_solaris8_sparc_test.erl159
-rw-r--r--lib/inets/test/ftp_solaris9_sparc_test.erl158
-rw-r--r--lib/inets/test/ftp_suite_lib.erl361
-rw-r--r--lib/inets/test/ftp_ticket_test.erl61
-rw-r--r--lib/inets/test/ftp_windows_2003_server_test.erl167
-rw-r--r--lib/inets/test/ftp_windows_xp_test.erl157
-rw-r--r--lib/inets/test/http_format_SUITE.erl24
-rw-r--r--lib/inets/test/httpc_SUITE.erl4904
-rw-r--r--lib/inets/test/httpc_SUITE_data/ssl_client_cert.pem45
-rw-r--r--lib/inets/test/httpc_SUITE_data/ssl_server_cert.pem45
-rw-r--r--lib/inets/test/httpc_cookie_SUITE.erl3
-rw-r--r--lib/inets/test/httpc_proxy_SUITE.erl592
-rw-r--r--lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf87
-rw-r--r--lib/inets/test/httpc_proxy_SUITE_data/apache2/htdocs/index.html4
-rwxr-xr-xlib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh198
-rw-r--r--lib/inets/test/httpd_1_0.erl33
-rw-r--r--lib/inets/test/httpd_1_1.erl12
-rw-r--r--lib/inets/test/httpd_SUITE.erl3340
-rw-r--r--lib/inets/test/httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip1
-rw-r--r--lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_client.pem22
-rw-r--r--lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_server.pem22
-rw-r--r--lib/inets/test/httpd_all.erl239
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl158
-rw-r--r--lib/inets/test/httpd_basic_SUITE_data/Makefile.src14
-rw-r--r--lib/inets/test/httpd_basic_SUITE_data/cgi_sleep.c26
l---------lib/inets/test/httpd_basic_SUITE_data/printenv.bat1
l---------lib/inets/test/httpd_basic_SUITE_data/printenv.sh1
-rw-r--r--lib/inets/test/httpd_block.erl53
-rw-r--r--lib/inets/test/httpd_mod.erl38
-rw-r--r--lib/inets/test/httpd_mod_SUITE.erl76
-rw-r--r--lib/inets/test/httpd_test_lib.erl35
-rw-r--r--lib/inets/test/inets_SUITE.erl7
-rw-r--r--lib/inets/test/inets_appup_test.erl15
-rw-r--r--lib/inets/test/inets_sup_SUITE.erl13
-rw-r--r--lib/inets/test/inets_test_lib.erl117
-rw-r--r--lib/inets/test/old_httpc_SUITE.erl3602
-rw-r--r--lib/inets/test/old_httpd_SUITE.erl2444
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/Makefile.src14
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/cgi_echo.c97
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/Makefile (renamed from lib/inets/test/httpd_SUITE_data/server_root/Makefile)23
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/auth/group3
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd4
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat7
-rwxr-xr-xlib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh6
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf (renamed from lib/inets/test/httpd_SUITE_data/server_root/conf/8080.conf)0
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf (renamed from lib/inets/test/httpd_SUITE_data/server_root/conf/8888.conf)0
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf (renamed from lib/inets/test/httpd_SUITE_data/server_root/conf/httpd.conf)24
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types (renamed from lib/inets/test/httpd_SUITE_data/server_root/conf/mime.types)3
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf (renamed from lib/inets/test/httpd_SUITE_data/server_root/conf/ssl.conf)0
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml60
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html9
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml25
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml20
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml19
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml19
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml23
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html25
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html12
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html7
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html4
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html1
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html9
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html10
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html9
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/README (renamed from lib/inets/test/httpd_SUITE_data/server_root/icons/README)0
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gifbin0 -> 246 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gifbin0 -> 242 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gifbin0 -> 247 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gifbin0 -> 2326 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gifbin0 -> 216 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gifbin0 -> 233 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gifbin0 -> 205 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gifbin0 -> 246 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gifbin0 -> 246 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gifbin0 -> 148 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gifbin0 -> 308 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gifbin0 -> 251 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gifbin0 -> 268 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gifbin0 -> 247 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gifbin0 -> 235 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gifbin0 -> 755 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gifbin0 -> 781 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gifbin0 -> 785 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gifbin0 -> 745 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gifbin0 -> 786 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gifbin0 -> 780 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gifbin0 -> 791 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gifbin0 -> 796 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gifbin0 -> 784 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gifbin0 -> 784 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gifbin0 -> 587 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gifbin0 -> 576 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gifbin0 -> 242 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gifbin0 -> 251 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gifbin0 -> 246 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gifbin0 -> 1038 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gifbin0 -> 214 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gifbin0 -> 225 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gifbin0 -> 163 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gifbin0 -> 238 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gifbin0 -> 236 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gifbin0 -> 225 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gifbin0 -> 242 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gifbin0 -> 243 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gifbin0 -> 219 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gifbin0 -> 221 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gifbin0 -> 220 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gifbin0 -> 249 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gifbin0 -> 217 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gifbin0 -> 223 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gifbin0 -> 1822 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gifbin0 -> 11977 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gifbin0 -> 274 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gifbin0 -> 309 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gifbin0 -> 286 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gifbin0 -> 268 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gifbin0 -> 276 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gifbin0 -> 172 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gifbin0 -> 249 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gifbin0 -> 243 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gifbin0 -> 237 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gifbin0 -> 251 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gifbin0 -> 249 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gifbin0 -> 188 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gifbin0 -> 198 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gifbin0 -> 198 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gifbin0 -> 191 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gifbin0 -> 193 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gifbin0 -> 189 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gifbin0 -> 186 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gifbin0 -> 185 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gifbin0 -> 173 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gifbin0 -> 254 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gifbin0 -> 2748 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gifbin0 -> 244 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gifbin0 -> 267 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gifbin0 -> 172 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gifbin0 -> 258 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gifbin0 -> 263 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gifbin0 -> 242 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gifbin0 -> 248 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gifbin0 -> 221 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gifbin0 -> 285 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gifbin0 -> 264 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gifbin0 -> 89 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gifbin0 -> 53 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gifbin0 -> 243 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gifbin0 -> 251 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gifbin0 -> 229 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gifbin0 -> 242 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gifbin0 -> 245 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gifbin0 -> 164 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gifbin0 -> 236 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gifbin0 -> 236 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gifbin0 -> 228 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gifbin0 -> 261 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip0
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem31
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem31
-rw-r--r--lib/inets/test/uri_SUITE.erl159
180 files changed, 11849 insertions, 8868 deletions
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index 0fc98eff6f..609396273d 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-2014. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -149,40 +149,31 @@ INETS_ROOT = ../../inets
MODULES = \
inets_test_lib \
+ erl_make_certs \
ftp_SUITE \
+ ftp_suite_lib \
ftp_format_SUITE \
- ftp_solaris8_sparc_test \
- ftp_solaris9_sparc_test \
- ftp_solaris10_sparc_test \
- ftp_solaris10_x86_test \
- ftp_linux_x86_test \
- ftp_linux_ppc_test \
- ftp_macosx_x86_test \
- ftp_macosx_ppc_test \
- ftp_openbsd_x86_test \
- ftp_freebsd_x86_test \
- ftp_netbsd_x86_test \
- ftp_windows_xp_test \
- ftp_windows_2003_server_test \
- ftp_suite_lib \
- ftp_ticket_test \
http_format_SUITE \
httpc_SUITE \
httpc_cookie_SUITE \
+ httpc_proxy_SUITE \
httpd_SUITE \
+ old_httpd_SUITE \
httpd_basic_SUITE \
httpd_mod \
httpd_block \
httpd_load \
httpd_time_test \
httpd_1_1 \
+ httpd_1_0 \
httpd_test_lib \
inets_sup_SUITE \
inets_SUITE \
inets_app_test \
inets_appup_test \
tftp_test_lib \
- tftp_SUITE
+ tftp_SUITE \
+ uri_SUITE
EBIN = .
@@ -212,8 +203,8 @@ INETS_FILES = inets.config $(INETS_SPECS)
# inets_tftp_suite
INETS_DATADIRS = inets_SUITE_data inets_sup_SUITE_data
-HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data
-HTTPC_DATADIRS = httpc_SUITE_data
+HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data
+HTTPC_DATADIRS = httpc_SUITE_data httpc_proxy_SUITE_data
FTP_DATADIRS = ftp_SUITE_data
DATADIRS = $(INETS_DATADIRS) $(HTTPD_DATADIRS) $(HTTPC_DATADIRS) $(FTP_DATADIRS)
diff --git a/lib/inets/test/erl_make_certs.erl b/lib/inets/test/erl_make_certs.erl
new file mode 100644
index 0000000000..bac88dc277
--- /dev/null
+++ b/lib/inets/test/erl_make_certs.erl
@@ -0,0 +1,429 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Create test certificates
+
+-module(erl_make_certs).
+-include_lib("public_key/include/public_key.hrl").
+
+-export([make_cert/1, gen_rsa/1, verify_signature/3, write_pem/3]).
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% @doc Create and return a der encoded certificate
+%% Option Default
+%% -------------------------------------------------------
+%% digest sha1
+%% validity {date(), date() + week()}
+%% version 3
+%% subject [] list of the following content
+%% {name, Name}
+%% {email, Email}
+%% {city, City}
+%% {state, State}
+%% {org, Org}
+%% {org_unit, OrgUnit}
+%% {country, Country}
+%% {serial, Serial}
+%% {title, Title}
+%% {dnQualifer, DnQ}
+%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
+%% (obs IssuerKey migth be {Key, Password}
+%% key = KeyFile|KeyBin|rsa|dsa Subject PublicKey rsa or dsa generates key
+%%
+%%
+%% (OBS: The generated keys are for testing only)
+%% @spec ([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
+%% @end
+%%--------------------------------------------------------------------
+
+make_cert(Opts) ->
+ SubjectPrivateKey = get_key(Opts),
+ {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
+ Cert = public_key:pkix_sign(TBSCert, IssuerKey),
+ true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
+ {Cert, encode_key(SubjectPrivateKey)}.
+
+%%--------------------------------------------------------------------
+%% @doc Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem"
+%% @spec (::string(), ::string(), {Cert,Key}) -> ok
+%% @end
+%%--------------------------------------------------------------------
+write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
+ ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
+ [{'Certificate', Cert, not_encrypted}]),
+ ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
+
+%%--------------------------------------------------------------------
+%% @doc Creates a rsa key (OBS: for testing only)
+%% the size are in bytes
+%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
+%% @end
+%%--------------------------------------------------------------------
+gen_rsa(Size) when is_integer(Size) ->
+ Key = gen_rsa2(Size),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% @doc Creates a dsa key (OBS: for testing only)
+%% the sizes are in bytes
+%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
+%% @end
+%%--------------------------------------------------------------------
+gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
+ Key = gen_dsa2(LSize, NSize),
+ {Key, encode_key(Key)}.
+
+%%--------------------------------------------------------------------
+%% @doc Verifies cert signatures
+%% @spec (::binary(), ::tuple()) -> ::boolean()
+%% @end
+%%--------------------------------------------------------------------
+verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
+ Key = decode_key(DerKey),
+ case Key of
+ #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
+ public_key:pkix_verify(DerEncodedCert,
+ #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
+ #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
+ public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}})
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_key(Opts) ->
+ case proplists:get_value(key, Opts) of
+ undefined -> make_key(rsa, Opts);
+ rsa -> make_key(rsa, Opts);
+ dsa -> make_key(dsa, Opts);
+ Key ->
+ Password = proplists:get_value(password, Opts, no_passwd),
+ decode_key(Key, Password)
+ end.
+
+decode_key({Key, Pw}) ->
+ decode_key(Key, Pw);
+decode_key(Key) ->
+ decode_key(Key, no_passwd).
+
+
+decode_key(#'RSAPublicKey'{} = Key,_) ->
+ Key;
+decode_key(#'RSAPrivateKey'{} = Key,_) ->
+ Key;
+decode_key(#'DSAPrivateKey'{} = Key,_) ->
+ Key;
+decode_key(PemEntry = {_,_,_}, Pw) ->
+ public_key:pem_entry_decode(PemEntry, Pw);
+decode_key(PemBin, Pw) ->
+ [KeyInfo] = public_key:pem_decode(PemBin),
+ decode_key(KeyInfo, Pw).
+
+encode_key(Key = #'RSAPrivateKey'{}) ->
+ {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
+ {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
+encode_key(Key = #'DSAPrivateKey'{}) ->
+ {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
+ {'DSAPrivateKey', list_to_binary(Der), not_encrypted}.
+
+make_tbs(SubjectKey, Opts) ->
+ Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
+
+ IssuerProp = proplists:get_value(issuer, Opts, true),
+ {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
+
+ {Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
+
+ SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
+ parameters = Parameters},
+ Subject = case IssuerProp of
+ true -> %% Is a Root Ca
+ Issuer;
+ _ ->
+ subject(proplists:get_value(subject, Opts),false)
+ end,
+
+ {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
+ signature = SignAlgo,
+ issuer = Issuer,
+ validity = validity(Opts),
+ subject = Subject,
+ subjectPublicKeyInfo = publickey(SubjectKey),
+ version = Version,
+ extensions = extensions(Opts)
+ }, IssuerKey}.
+
+issuer(true, Opts, SubjectKey) ->
+ %% Self signed
+ {subject(proplists:get_value(subject, Opts), true), SubjectKey};
+issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
+ {issuer_der(Issuer), decode_key(IssuerKey)};
+issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
+ {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
+ {issuer_der(Cert), decode_key(IssuerKey)}.
+
+issuer_der(Issuer) ->
+ Decoded = public_key:pkix_decode_cert(Issuer, otp),
+ #'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
+ #'OTPTBSCertificate'{subject=Subject} = Tbs,
+ Subject.
+
+subject(undefined, IsRootCA) ->
+ User = if IsRootCA -> "RootCA"; true -> user() end,
+ Opts = [{email, User ++ "@erlang.org"},
+ {name, User},
+ {city, "Stockholm"},
+ {country, "SE"},
+ {org, "erlang"},
+ {org_unit, "testing dep"}],
+ subject(Opts);
+subject(Opts, _) ->
+ subject(Opts).
+
+user() ->
+ case os:getenv("USER") of
+ false ->
+ "test_user";
+ User ->
+ User
+ end.
+
+subject(SubjectOpts) when is_list(SubjectOpts) ->
+ Encode = fun(Opt) ->
+ {Type,Value} = subject_enc(Opt),
+ [#'AttributeTypeAndValue'{type=Type, value=Value}]
+ end,
+ {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
+
+%% Fill in the blanks
+subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
+subject_enc({email, Email}) -> {?'id-emailAddress', Email};
+subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
+subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
+subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
+subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
+subject_enc({country, Country}) -> {?'id-at-countryName', Country};
+subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
+subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
+subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
+subject_enc(Other) -> Other.
+
+
+extensions(Opts) ->
+ case proplists:get_value(extensions, Opts, []) of
+ false ->
+ asn1_NOVALUE;
+ Exts ->
+ lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
+ end.
+
+default_extensions(Exts) ->
+ Def = [{key_usage,undefined},
+ {subject_altname, undefined},
+ {issuer_altname, undefined},
+ {basic_constraints, default},
+ {name_constraints, undefined},
+ {policy_constraints, undefined},
+ {ext_key_usage, undefined},
+ {inhibit_any, undefined},
+ {auth_key_id, undefined},
+ {subject_key_id, undefined},
+ {policy_mapping, undefined}],
+ Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
+ Exts ++ lists:foldl(Filter, Def, Exts).
+
+extension({_, undefined}) -> [];
+extension({basic_constraints, Data}) ->
+ case Data of
+ default ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true},
+ critical=true};
+ false ->
+ [];
+ Len when is_integer(Len) ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
+ critical=true};
+ _ ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = Data}
+ end;
+extension({Id, Data, Critical}) ->
+ #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
+
+
+publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
+ Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
+ subjectPublicKey = Public};
+publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
+ Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
+ #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
+
+validity(Opts) ->
+ DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
+ DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
+ {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
+ Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end,
+ #'Validity'{notBefore={generalTime, Format(DefFrom)},
+ notAfter ={generalTime, Format(DefTo)}}.
+
+sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
+ Type = case proplists:get_value(digest, Opts, sha1) of
+ sha1 -> ?'sha1WithRSAEncryption';
+ sha512 -> ?'sha512WithRSAEncryption';
+ sha384 -> ?'sha384WithRSAEncryption';
+ sha256 -> ?'sha256WithRSAEncryption';
+ md5 -> ?'md5WithRSAEncryption';
+ md2 -> ?'md2WithRSAEncryption'
+ end,
+ {Type, 'NULL'};
+sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
+
+make_key(rsa, _Opts) ->
+ %% (OBS: for testing only)
+ gen_rsa2(64);
+make_key(dsa, _Opts) ->
+ gen_dsa2(128, 20). %% Bytes i.e. {1024, 160}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RSA key generation (OBS: for testing only)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53,
+ 47,43,41,37,31,29,23,19,17,13,11,7,5,3]).
+
+gen_rsa2(Size) ->
+ P = prime(Size),
+ Q = prime(Size),
+ N = P*Q,
+ Tot = (P - 1) * (Q - 1),
+ [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES),
+ {D1,D2} = extended_gcd(E, Tot),
+ D = erlang:max(D1,D2),
+ case D < E of
+ true ->
+ gen_rsa2(Size);
+ false ->
+ {Co1,Co2} = extended_gcd(Q, P),
+ Co = erlang:max(Co1,Co2),
+ #'RSAPrivateKey'{version = 'two-prime',
+ modulus = N,
+ publicExponent = E,
+ privateExponent = D,
+ prime1 = P,
+ prime2 = Q,
+ exponent1 = D rem (P-1),
+ exponent2 = D rem (Q-1),
+ coefficient = Co
+ }
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% DSA key generation (OBS: for testing only)
+%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
+%% and the fips_186-3.pdf
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+gen_dsa2(LSize, NSize) ->
+ Q = prime(NSize), %% Choose N-bit prime Q
+ X0 = prime(LSize),
+ P0 = prime((LSize div 2) +1),
+
+ %% Choose L-bit prime modulus P such that p–1 is a multiple of q.
+ case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of
+ error ->
+ gen_dsa2(LSize, NSize);
+ P ->
+ G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q.
+ %% such that This may be done by setting g = h^(p–1)/q mod p, commonly h=2 is used.
+
+ X = prime(20), %% Choose x by some random method, where 0 < x < q.
+ Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p.
+
+ #'DSAPrivateKey'{version=0, p=P, q=Q, g=G, y=Y, x=X}
+ end.
+
+%% See fips_186-3.pdf
+dsa_search(T, P0, Q, Iter) when Iter > 0 ->
+ P = 2*T*Q*P0 + 1,
+ case is_prime(crypto:mpint(P), 50) of
+ true -> P;
+ false -> dsa_search(T+1, P0, Q, Iter-1)
+ end;
+dsa_search(_,_,_,_) ->
+ error.
+
+
+%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+prime(ByteSize) ->
+ Rand = odd_rand(ByteSize),
+ crypto:erlint(prime_odd(Rand, 0)).
+
+prime_odd(Rand, N) ->
+ case is_prime(Rand, 50) of
+ true ->
+ Rand;
+ false ->
+ NotPrime = crypto:erlint(Rand),
+ prime_odd(crypto:mpint(NotPrime+2), N+1)
+ end.
+
+%% see http://en.wikipedia.org/wiki/Fermat_primality_test
+is_prime(_, 0) -> true;
+is_prime(Candidate, Test) ->
+ CoPrime = odd_rand(<<0,0,0,4, 10000:32>>, Candidate),
+ case crypto:mod_exp(CoPrime, Candidate, Candidate) of
+ CoPrime -> is_prime(Candidate, Test-1);
+ _ -> false
+ end.
+
+odd_rand(Size) ->
+ Min = 1 bsl (Size*8-1),
+ Max = (1 bsl (Size*8))-1,
+ odd_rand(crypto:mpint(Min), crypto:mpint(Max)).
+
+odd_rand(Min,Max) ->
+ Rand = <<Sz:32, _/binary>> = crypto:rand_uniform(Min,Max),
+ BitSkip = (Sz+4)*8-1,
+ case Rand of
+ Odd = <<_:BitSkip, 1:1>> -> Odd;
+ Even = <<_:BitSkip, 0:1>> ->
+ crypto:mpint(crypto:erlint(Even)+1)
+ end.
+
+extended_gcd(A, B) ->
+ case A rem B of
+ 0 ->
+ {0, 1};
+ N ->
+ {X, Y} = extended_gcd(B, N),
+ {Y, X-Y*(A div B)}
+ end.
+
+pem_to_der(File) ->
+ {ok, PemBin} = file:read_file(File),
+ public_key:pem_decode(PemBin).
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
diff --git a/lib/inets/test/ftp_SUITE.erl b/lib/inets/test/ftp_SUITE.erl
index 17e5f6777e..298e15a853 100644
--- a/lib/inets/test/ftp_SUITE.erl
+++ b/lib/inets/test/ftp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -18,110 +18,803 @@
%%
%%
+%%
+%% ct:run("../inets_test", ftp_SUITE).
+%%
+
-module(ftp_SUITE).
+-include_lib("kernel/include/file.hrl").
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
+-include("inets_test_lib.hrl").
-%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
-% -export([init_per_testcase/2, end_per_testcase/2]).
--export([init_per_suite/1, end_per_suite/1]).
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
-define(FTP_USER, "anonymous").
--define(FTP_PASS, passwd()).
--define(FTP_PORT, 21).
+-define(FTP_PASS(Cmnt), (fun({ok,__H}) -> "ftp_SUITE_"++Cmnt++"@" ++ __H;
+ (_) -> "ftp_SUITE_"++Cmnt++"@localhost"
+ end)(inet:gethostname())
+ ).
-define(BAD_HOST, "badhostname").
-define(BAD_USER, "baduser").
-define(BAD_DIR, "baddirectory").
--ifdef(ftp_debug_client).
--define(ftp_open(Host, Flags), do_ftp_open(Host, [debug] ++ Flags)).
--else.
--ifdef(ftp_trace_client).
--define(ftp_open(Host, Flags), do_ftp_open(Host, [trace] ++ Flags)).
--else.
--define(ftp_open(Host, Flags), do_ftp_open(Host, [verbose] ++ Flags)).
--endif.
--endif.
-
+go() -> ct:run_test([{suite,"ftp_SUITE"}, {logdir,"LOG"}]).
+gos() -> ct:run_test([{suite,"ftp_SUITE"}, {group,ftps_passive}, {logdir,"LOG"}]).
%%--------------------------------------------------------------------
-%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
-%% Arg - doc | suite
-%% Doc - string()
-%% Case - atom()
-%% Name of a test case function.
-%% Comment - string()
-%% Description: Returns documentation/test cases in this test suite
-%% or a skip tuple if the platform is not supported.
+%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-suite() -> [{ct_hooks, [ts_install_cth]}].
+all() ->
+ [
+ {group, ftp_passive},
+ {group, ftp_active},
+ {group, ftps_passive},
+ {group, ftps_active}
+ ].
-all() ->
+groups() ->
[
- {group, solaris8_test},
- {group, solaris9_test},
- {group, solaris10_test},
- {group, linux_x86_test},
- {group, linux_ppc_test},
- {group, macosx_x86_test},
- {group, macosx_ppc_test},
- {group, openbsd_test},
- {group, freebsd_test},
- {group, netbsd_test},
- {group, windows_xp_test},
- {group, windows_2003_server_test},
- {group, ticket_tests}
+ {ftp_passive, [], ftp_tests()},
+ {ftp_active, [], ftp_tests()},
+ {ftps_passive, [], ftp_tests()},
+ {ftps_active, [], ftp_tests()}
].
-groups() ->
+ftp_tests()->
[
- {solaris8_test, [], [{ftp_solaris8_sparc_test, all}]},
- {solaris9_test, [], [{ftp_solaris9_sparc_test, all}]},
- {solaris10_test, [], [{ftp_solaris10_sparc_test, all},
- {ftp_solaris10_x86_test, all}]},
- {linux_x86_test, [], [{ftp_linux_x86_test, all}]},
- {linux_ppc_test, [], [{ftp_linux_ppc_test, all}]},
- {macosx_x86_test, [], [{ftp_macosx_x86_test, all}]},
- {macosx_ppc_test, [], [{ftp_macosx_ppc_test, all}]},
- {openbsd_test, [], [{ftp_openbsd_x86_test, all}]},
- {freebsd_test, [], [{ftp_freebsd_x86_test, all}]},
- {netbsd_test, [], [{ftp_netbsd_x86_test, all}]},
- {windows_xp_test, [], [{ftp_windows_xp_test, all}]},
- {windows_2003_server_test, [], [{ftp_windows_2003_server_test, all}]},
- {ticket_tests, [], [{ftp_ticket_test, all}]}
+ user,
+ bad_user,
+ pwd,
+ cd,
+ lcd,
+ ls,
+ nlist,
+ rename,
+ delete,
+ mkdir,
+ rmdir,
+ send,
+ send_3,
+ send_bin,
+ send_chunk,
+ append,
+ append_bin,
+ append_chunk,
+ recv,
+ recv_3,
+ recv_bin,
+ recv_chunk,
+ type,
+ quote,
+ ip_v6_disabled
].
-init_per_group(_GroupName, Config) ->
- Config.
+%%--------------------------------------------------------------------
+
+%%% Config
+%%% key meaning
+%%% ................................................................
+%%% ftpservers list of servers to check if they are available
+%%% The element is:
+%%% {Name, % string(). The os command name
+%%% StartCommand, % fun()->{ok,start_result()} | {error,string()}.
+%%% % The command to start the daemon with.
+%%% ChkUp, % fun(start_result()) -> string(). Os command to check
+%%% % if the server is running. [] if not running.
+%%% % The string in string() is suitable for logging.
+%%% StopCommand, % fun(start_result()) -> void(). The command to stop the daemon with.
+%%% AugmentFun, % fun(config()) -> config() Adds two funs for transforming names of files
+%%% % and directories to the form they are returned from this server
+%%% ServerHost, % string(). Mostly "localhost"
+%%% ServerPort % pos_integer()
+%%% }
+%%%
+
+-define(default_ftp_servers,
+ [{"vsftpd",
+ fun(__CONF__) ->
+ DataDir = ?config(data_dir,__CONF__),
+ ConfFile = filename:join(DataDir, "vsftpd.conf"),
+ PrivDir = ?config(priv_dir,__CONF__),
+ AnonRoot = PrivDir,
+ Cmd = ["vsftpd "++filename:join(DataDir,"vsftpd.conf"),
+ " -oftpd_banner=erlang_otp_testing",
+ " -oanon_root=\"",AnonRoot,"\"",
+ " -orsa_cert_file=\"",filename:join(DataDir,"server-cert.pem"),"\"",
+ " -orsa_private_key_file=\"",filename:join(DataDir,"server-key.pem"),"\""
+ ],
+ Result = os:cmd(Cmd),
+ ct:log("Config file:~n~s~n~nServer start command:~n ~s~nResult:~n ~p",
+ [case file:read_file(ConfFile) of
+ {ok,X} -> X;
+ _ -> ""
+ end,
+ Cmd, Result
+ ]),
+ case Result of
+ [] -> {ok,'dont care'};
+ [Msg] -> {error,Msg}
+ end
+ end,
+ fun(_StartResult) -> os:cmd("ps ax | grep erlang_otp_testing | grep -v grep")
+ end,
+ fun(_StartResult) -> os:cmd("kill `ps ax | grep erlang_otp_testing | awk '/vsftpd/{print $1}'`")
+ end,
+ fun(__CONF__) ->
+ AnonRoot = ?config(priv_dir,__CONF__),
+ [{id2ftp, fun(Id) -> filename:join(AnonRoot,Id) end},
+ {id2ftp_result,fun(Id) -> filename:join(AnonRoot,Id) end} | __CONF__]
+ end,
+ "localhost",
+ 9999
+ }
+ ]
+ ).
+
+
+init_per_suite(Config) ->
+ case find_executable(Config) of
+ false ->
+ {skip, "No ftp server found"};
+ {ok,Data} ->
+ TstDir = filename:join(?config(priv_dir,Config), "test"),
+ file:make_dir(TstDir),
+ make_cert_files(dsa, rsa, "server-", ?config(data_dir,Config)),
+ start_ftpd([{test_dir,TstDir},
+ {ftpd_data,Data}
+ | Config])
+ end.
+
+end_per_suite(Config) ->
+ ps_ftpd(Config),
+ stop_ftpd(Config),
+ ps_ftpd(Config),
+ ok.
+
+%%--------------------------------------------------------------------
+init_per_group(_Group, Config) -> Config.
+
+end_per_group(_Group, Config) -> Config.
+
+%%--------------------------------------------------------------------
+init_per_testcase(Case, Config0) ->
+ Group = proplists:get_value(name,?config(tc_group_properties,Config0)),
+ try ?MODULE:Case(doc) of
+ Msg -> ct:comment(Msg)
+ catch
+ _:_-> ok
+ end,
+ TLS = [{tls,[{reuse_sessions,true}]}],
+ ACTIVE = [{mode,active}],
+ PASSIVE = [{mode,passive}],
+ ExtraOpts = [verbose],
+ Config =
+ case Group of
+ ftp_active -> ftp__open(Config0, ACTIVE ++ExtraOpts);
+ ftps_active -> ftp__open(Config0, TLS++ ACTIVE ++ExtraOpts);
+ ftp_passive -> ftp__open(Config0, PASSIVE ++ExtraOpts);
+ ftps_passive -> ftp__open(Config0, TLS++PASSIVE ++ExtraOpts)
+ end,
+ case Case of
+ user -> Config;
+ bad_user -> Config;
+ _ ->
+ Pid = ?config(ftp,Config),
+ ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS(atom_to_list(Group)++"-"++atom_to_list(Case)) ),
+ ok = ftp:cd(Pid, ?config(priv_dir,Config)),
+ Config
+ end.
+
+
+end_per_testcase(user, _Config) -> ok;
+end_per_testcase(bad_user, _Config) -> ok;
+end_per_testcase(_Case, Config) ->
+ case ?config(tc_status,Config) of
+ ok -> ok;
+ _ ->
+ try ftp:latest_ctrl_response(?config(ftp,Config))
+ of
+ {ok,S} -> ct:log("***~n*** Latest ctrl channel response:~n*** ~p~n***",[S])
+ catch
+ _:_ -> ok
+ end
+ end,
+ ftp__close(Config).
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+user(doc) -> ["Open an ftp connection to a host, and logon as anonymous ftp, then logoff"];
+user(Config) ->
+ Pid = ?config(ftp, Config),
+ ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS("")),% logon
+ ok = ftp:close(Pid), % logoff
+ {error,eclosed} = ftp:pwd(Pid), % check logoff result
+ ok.
+
+%%-------------------------------------------------------------------------
+bad_user(doc) -> ["Open an ftp connection to a host, and logon with bad user."];
+bad_user(Config) ->
+ Pid = ?config(ftp, Config),
+ {error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS("")),
+ ok.
+
+%%-------------------------------------------------------------------------
+pwd(doc) -> ["Test ftp:pwd/1 & ftp:lpwd/1"];
+pwd(Config0) ->
+ Config = set_state([reset], Config0),
+ Pid = ?config(ftp, Config),
+ {ok, PWD} = ftp:pwd(Pid),
+ {ok, PathLpwd} = ftp:lpwd(Pid),
+ PWD = id2ftp_result("", Config),
+ PathLpwd = id2ftp_result("", Config).
+
+%%-------------------------------------------------------------------------
+cd(doc) -> ["Open an ftp connection, log on as anonymous ftp, and cd to a"
+ "directory and to a non-existent directory."];
+cd(Config0) ->
+ Dir = "test",
+ Config = set_state([reset,{mkdir,Dir}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:cd(Pid, id2ftp(Dir,Config)),
+ {ok, PWD} = ftp:pwd(Pid),
+ ExpectedPWD = id2ftp_result(Dir, Config),
+ PWD = ExpectedPWD,
+ {error, epath} = ftp:cd(Pid, ?BAD_DIR).
+
+%%-------------------------------------------------------------------------
+lcd(doc) ->
+ ["Test api function ftp:lcd/2"];
+lcd(Config0) ->
+ Dir = "test",
+ Config = set_state([reset,{mkdir,Dir}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:lcd(Pid, id2ftp(Dir,Config)),
+ {ok, PWD} = ftp:lpwd(Pid),
+ ExpectedPWD = id2ftp_result(Dir, Config),
+ PWD = ExpectedPWD,
+ {error, epath} = ftp:lcd(Pid, ?BAD_DIR).
+
+%%-------------------------------------------------------------------------
+ls(doc) -> ["Open an ftp connection; ls the current directory, and the "
+ "\"test\" directory. We assume that ls never fails, since "
+ "it's output is meant to be read by humans. "];
+ls(Config0) ->
+ Config = set_state([reset,{mkdir,"test"}], Config0),
+ Pid = ?config(ftp, Config),
+ {ok, _R1} = ftp:ls(Pid),
+ {ok, _R2} = ftp:ls(Pid, id2ftp("test",Config)),
+ %% neither nlist nor ls operates on a directory
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
+ %% of files (including wildcards).
+ case ?config(wildcard_support, Config) of
+ true ->
+ {ok, _R3} = ftp:ls(Pid, id2ftp("te*",Config));
+ _ ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+nlist(doc) -> ["Open an ftp connection; nlist the current directory, and the "
+ "\"test\" directory. Nlist does not behave consistenly over "
+ "operating systems. On some it is an error to have an empty "
+ "directory."];
+nlist(Config0) ->
+ Config = set_state([reset,{mkdir,"test"}], Config0),
+ Pid = ?config(ftp, Config),
+ {ok, _R1} = ftp:nlist(Pid),
+ {ok, _R2} = ftp:nlist(Pid, id2ftp("test",Config)),
+ %% neither nlist nor ls operates on a directory
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
+ %% of files (including wildcards).
+ case ?config(wildcard_support, Config) of
+ true ->
+ {ok, _R3} = ftp:nlist(Pid, id2ftp("te*",Config));
+ _ ->
+ ok
+ end.
+
+%%-------------------------------------------------------------------------
+rename(doc) -> ["Rename a file."];
+rename(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ OldFile = "old.txt",
+ NewFile = "new.txt",
+ Config = set_state([reset,{mkfile,OldFile,Contents}], Config0),
+ Pid = ?config(ftp, Config),
+
+ ok = ftp:rename(Pid,
+ id2ftp(OldFile,Config),
+ id2ftp(NewFile,Config)),
+
+ true = (chk_file(NewFile,Contents,Config)
+ and chk_no_file([OldFile],Config)).
+
+
+%%-------------------------------------------------------------------------
+send(doc) -> ["Transfer a file with ftp using send/2."];
+send(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ SrcDir = "data",
+ File = "file.txt",
+ Config = set_state([reset,{mkfile,[SrcDir,File],Contents}], Config0),
+ Pid = ?config(ftp, Config),
+
+chk_no_file([File],Config),
+chk_file([SrcDir,File],Contents,Config),
+
+ ok = ftp:lcd(Pid, id2ftp(SrcDir,Config)),
+ ok = ftp:cd(Pid, id2ftp("",Config)),
+ ok = ftp:send(Pid, File),
+
+ chk_file(File, Contents, Config).
+
+%%-------------------------------------------------------------------------
+send_3(doc) -> ["Transfer a file with ftp using send/3."];
+send_3(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ Dir = "incoming",
+ File = "file.txt",
+ RemoteFile = "remfile.txt",
+ Config = set_state([reset,{mkfile,File,Contents},{mkdir,Dir}], Config0),
+ Pid = ?config(ftp, Config),
+
+ ok = ftp:cd(Pid, id2ftp(Dir,Config)),
+ ok = ftp:lcd(Pid, id2ftp("",Config)),
+ ok = ftp:send(Pid, File, RemoteFile),
+
+ chk_file([Dir,RemoteFile], Contents, Config).
+
+%%-------------------------------------------------------------------------
+send_bin(doc) -> ["Send a binary."];
+send_bin(Config0) ->
+ BinContents = <<"ftp_SUITE test ...">>,
+ File = "file.txt",
+ Config = set_state([reset], Config0),
+ Pid = ?config(ftp, Config),
+ {error, enotbinary} = ftp:send_bin(Pid, "some string", id2ftp(File,Config)),
+ ok = ftp:send_bin(Pid, BinContents, id2ftp(File,Config)),
+ chk_file(File, BinContents, Config).
+
+%%-------------------------------------------------------------------------
+send_chunk(doc) -> ["Send a binary using chunks."];
+send_chunk(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ File = "file.txt",
+ Config = set_state([reset,{mkdir,"incoming"}], Config0),
+ Pid = ?config(ftp, Config),
+
+ ok = ftp:send_chunk_start(Pid, id2ftp(File,Config)),
+ {error, echunk} = ftp:cd(Pid, "incoming"),
+ {error, enotbinary} = ftp:send_chunk(Pid, "some string"),
+ ok = ftp:send_chunk(Pid, Contents),
+ ok = ftp:send_chunk(Pid, Contents),
+ ok = ftp:send_chunk_end(Pid),
+ chk_file(File, <<Contents/binary,Contents/binary>>, Config).
+
+%%-------------------------------------------------------------------------
+delete(doc) -> ["Delete a file."];
+delete(Config0) ->
+ Contents = <<"ftp_SUITE test ...">>,
+ File = "file.txt",
+ Config = set_state([reset,{mkfile,File,Contents}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:delete(Pid, id2ftp(File,Config)),
+ chk_no_file([File], Config).
+
+%%-------------------------------------------------------------------------
+mkdir(doc) -> ["Make a remote directory."];
+mkdir(Config0) ->
+ NewDir = "new_dir",
+ Config = set_state([reset], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:mkdir(Pid, id2ftp(NewDir,Config)),
+ chk_dir([NewDir], Config).
+
+%%-------------------------------------------------------------------------
+rmdir(doc) -> ["Remove a directory."];
+rmdir(Config0) ->
+ Dir = "dir",
+ Config = set_state([reset,{mkdir,Dir}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:rmdir(Pid, id2ftp(Dir,Config)),
+ chk_no_dir([Dir], Config).
+
+%%-------------------------------------------------------------------------
+append(doc) -> ["Append a local file twice to a remote file"];
+append(Config0) ->
+ SrcFile = "f_src.txt",
+ DstFile = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset,{mkfile,SrcFile,Contents}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
+ ok = ftp:append(Pid, id2ftp(SrcFile,Config), id2ftp(DstFile,Config)),
+ chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
+
+%%-------------------------------------------------------------------------
+append_bin(doc) -> ["Append a local file twice to a remote file using append_bin"];
+append_bin(Config0) ->
+ DstFile = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
+ ok = ftp:append_bin(Pid, Contents, id2ftp(DstFile,Config)),
+ chk_file(DstFile, <<Contents/binary,Contents/binary>>, Config).
+
+%%-------------------------------------------------------------------------
+append_chunk(doc) -> ["Append chunks."];
+append_chunk(Config0) ->
+ File = "f_dst.txt",
+ Contents = [<<"ER">>,<<"LE">>,<<"RL">>],
+ Config = set_state([reset], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:append_chunk_start(Pid, id2ftp(File,Config)),
+ {error, enotbinary} = ftp:append_chunk(Pid, binary_to_list(lists:nth(1,Contents))),
+ ok = ftp:append_chunk(Pid,lists:nth(1,Contents)),
+ ok = ftp:append_chunk(Pid,lists:nth(2,Contents)),
+ ok = ftp:append_chunk(Pid,lists:nth(3,Contents)),
+ ok = ftp:append_chunk_end(Pid),
+ chk_file(File, <<"ERLERL">>, Config).
+
+%%-------------------------------------------------------------------------
+recv(doc) -> ["Receive a file using recv/2"];
+recv(Config0) ->
+ File = "f_dst.txt",
+ SrcDir = "a_dir",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,[SrcDir,File],Contents}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:cd(Pid, id2ftp(SrcDir,Config)),
+ ok = ftp:lcd(Pid, id2ftp("",Config)),
+ ok = ftp:recv(Pid, File),
+ chk_file(File, Contents, Config).
+
+%%-------------------------------------------------------------------------
+recv_3(doc) -> ["Receive a file using recv/3"];
+recv_3(Config0) ->
+ DstFile = "f_src.txt",
+ SrcFile = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,SrcFile,Contents}], Config0),
+ Pid = ?config(ftp, Config),
+ ok = ftp:cd(Pid, id2ftp("",Config)),
+ ok = ftp:recv(Pid, SrcFile, id2abs(DstFile,Config)),
+ chk_file(DstFile, Contents, Config).
+
+%%-------------------------------------------------------------------------
+recv_bin(doc) -> ["Receive a file as a binary."];
+recv_bin(Config0) ->
+ File = "f_dst.txt",
+ Contents = <<"ftp_SUITE test ...">>,
+ Config = set_state([reset, {mkfile,File,Contents}], Config0),
+ Pid = ?config(ftp, Config),
+ {ok,Received} = ftp:recv_bin(Pid, id2ftp(File,Config)),
+ find_diff(Received, Contents).
+
+%%-------------------------------------------------------------------------
+recv_chunk(doc) -> ["Receive a file using chunk-wise."];
+recv_chunk(Config0) ->
+ File = "big_file.txt",
+ Contents = list_to_binary( lists:duplicate(1000, lists:seq(0,255)) ),
+ Config = set_state([reset, {mkfile,File,Contents}], Config0),
+ Pid = ?config(ftp, Config),
+ {{error, "ftp:recv_chunk_start/2 not called"},_} = recv_chunk(Pid, <<>>),
+ ok = ftp:recv_chunk_start(Pid, id2ftp(File,Config)),
+ {ok, ReceivedContents, _Ncunks} = recv_chunk(Pid, <<>>),
+ find_diff(ReceivedContents, Contents).
+
+recv_chunk(Pid, Acc) -> recv_chunk(Pid, Acc, 0).
-end_per_group(_GroupName, Config) ->
- Config.
+recv_chunk(Pid, Acc, N) ->
+ case ftp:recv_chunk(Pid) of
+ ok -> {ok, Acc, N};
+ {ok, Bin} -> recv_chunk(Pid, <<Acc/binary, Bin/binary>>, N+1);
+ Error -> {Error, N}
+ end.
+%%-------------------------------------------------------------------------
+type(doc) -> ["Test that we can change btween ASCCI and binary transfer mode"];
+type(Config) ->
+ Pid = ?config(ftp, Config),
+ ok = ftp:type(Pid, ascii),
+ ok = ftp:type(Pid, binary),
+ ok = ftp:type(Pid, ascii),
+ {error, etype} = ftp:type(Pid, foobar).
+%%-------------------------------------------------------------------------
+quote(doc) -> [""];
+quote(Config) ->
+ Pid = ?config(ftp, Config),
+ ["257 \""++_Rest] = ftp:quote(Pid, "pwd"), %% 257
+ [_| _] = ftp:quote(Pid, "help"),
+ %% This negativ test causes some ftp servers to hang. This test
+ %% is not important for the client, so we skip it for now.
+ %%["425 Can't build data connection: Connection refused."]
+ %% = ftp:quote(Pid, "list"),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+ip_v6_disabled(doc) -> ["Test ipv4 command PORT"];
+ip_v6_disabled(_Config) ->
+ %%% FIXME!!!! What is this???
+ ok.%% send(Config).
+
+%%-------------------------------------------------------------------------
+%% big_one(doc) ->
+%% ["Create a local file and transfer it to the remote host into the "
+%% "the \"incoming\" directory, remove "
+%% "the local file. Then open a new connection; cd to \"incoming\", "
+%% "lcd to the private directory; receive the file; delete the "
+%% "remote file; close connection; check that received file is in "
+%% "the correct directory; cleanup." ];
+%% big_one(Config) ->
+%% Pid = ?config(ftp, Config),
+%% do_recv(Pid, Config).
+%% do_recv(Pid, Config) ->
+%% PrivDir = ?config(priv_dir, Config),
+%% File = ?config(file, Config),
+%% Newfile = ?config(new_file, Config),
+%% AbsFile = filename:absname(File, PrivDir),
+%% Contents = "ftp_SUITE:recv test ...",
+%% ok = file:write_file(AbsFile, list_to_binary(Contents)),
+%% ok = ftp:cd(Pid, "incoming"),
+%% ftp:delete(Pid, File), % reset
+%% ftp:lcd(Pid, PrivDir),
+%% ok = ftp:send(Pid, File),
+%% ok = file:delete(AbsFile), % cleanup
+%% test_server:sleep(100),
+%% ok = ftp:lcd(Pid, PrivDir),
+%% ok = ftp:recv(Pid, File),
+%% {ok, Files} = file:list_dir(PrivDir),
+%% true = lists:member(File, Files),
+%% ok = file:delete(AbsFile), % cleanup
+%% ok = ftp:recv(Pid, File, Newfile),
+%% ok = ftp:delete(Pid, File), % cleanup
+%% ok.
+
+%%--------------------------------------------------------------------
+%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
+
+make_cert_files(Alg1, Alg2, Prefix, Dir) ->
+ CaInfo = {CaCert,_} = erl_make_certs:make_cert([{key,Alg1}]),
+ {Cert,CertKey} = erl_make_certs:make_cert([{key,Alg2},{issuer,CaInfo}]),
+ CaCertFile = filename:join(Dir, Prefix++"cacerts.pem"),
+ CertFile = filename:join(Dir, Prefix++"cert.pem"),
+ KeyFile = filename:join(Dir, Prefix++"key.pem"),
+ der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
+ der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
+ der_to_pem(KeyFile, [CertKey]),
+ ok.
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
+
+%%--------------------------------------------------------------------
+chk_file(Path=[C|_], ExpectedContents, Config) when 0<C,C=<255 ->
+ chk_file([Path], ExpectedContents, Config);
+
+chk_file(PathList, ExpectedContents, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file(AbsPath) of
+ {ok,ExpectedContents} ->
+ true;
+ {ok,ReadContents} ->
+ {error,{diff,Pos,RC,LC}} = find_diff(ReadContents, ExpectedContents, 1),
+ ct:log("Bad contents of ~p.~nGot:~n~p~nExpected:~n~p~nDiff at pos ~p ~nRead: ~p~nExp : ~p",
+ [AbsPath,ReadContents,ExpectedContents,Pos,RC,LC]),
+ ct:fail("Bad contents of ~p", [Path]);
+ {error,Error} ->
+ try begin
+ {ok,CWD} = file:get_cwd(),
+ ct:log("file:get_cwd()=~p~nfiles:~n~p",[CWD,file:list_dir(CWD)])
+ end
+ of _ -> ok
+ catch _:_ ->ok
+ end,
+ ct:fail("Error reading ~p: ~p",[Path,Error])
+ end.
+
+
+chk_no_file(Path=[C|_], Config) when 0<C,C=<255 ->
+ chk_no_file([Path], Config);
+
+chk_no_file(PathList, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file(AbsPath) of
+ {error,enoent} ->
+ true;
+ {ok,Contents} ->
+ ct:log("File ~p exists although it shouldn't. Contents:~n~p",
+ [AbsPath,Contents]),
+ ct:fail("File exists: ~p", [Path]);
+ {error,Error} ->
+ ct:fail("Unexpected error reading ~p: ~p",[Path,Error])
+ end.
+
+
+chk_dir(Path=[C|_], Config) when 0<C,C=<255 ->
+ chk_dir([Path], Config);
+
+chk_dir(PathList, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file_info(AbsPath) of
+ {ok, #file_info{type=directory}} ->
+ true;
+ {ok, #file_info{type=Type}} ->
+ ct:fail("Expected dir ~p is a ~p",[Path,Type]);
+ {error,Error} ->
+ ct:fail("Expected dir ~p: ~p",[Path,Error])
+ end.
+
+chk_no_dir(PathList, Config) ->
+ Path = filename:join(PathList),
+ AbsPath = id2abs(Path,Config),
+ case file:read_file_info(AbsPath) of
+ {error,enoent} ->
+ true;
+ {ok, #file_info{type=directory}} ->
+ ct:fail("Dir ~p erroneously exists",[Path]);
+ {ok, #file_info{type=Type}} ->
+ ct:fail("~p ~p erroneously exists",[Type,Path]);
+ {error,Error} ->
+ ct:fail("Unexpected error for ~p: ~p",[Path,Error])
+ end.
+
+
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+%% find a suitable ftpd
%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
+find_executable(Config) ->
+ FTPservers = case ?config(ftpservers,Config) of
+ undefined -> ?default_ftp_servers;
+ L -> L
+ end,
+ case lists:dropwhile(fun not_available/1, FTPservers) of
+ [] -> false;
+ [FTPD_data|_] -> {ok, FTPD_data}
+ end.
+
+not_available({Name,_StartCmd,_ChkUp,_StopCommand,_ConfigUpd,_Host,_Port}) ->
+ os:find_executable(Name) == false.
+
%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- inets:start(),
+%% start/stop of ftpd
+%%
+start_ftpd(Config) ->
+ {Name,StartCmd,_ChkUp,_StopCommand,ConfigRewrite,Host,Port} = ?config(ftpd_data, Config),
+ case StartCmd(Config) of
+ {ok,StartResult} ->
+ [{ftpd_host,Host},
+ {ftpd_port,Port},
+ {ftpd_start_result,StartResult} | ConfigRewrite(Config)];
+ {error,Msg} ->
+ {skip, [Name," not started: ",Msg]}
+ end.
+
+stop_ftpd(Config) ->
+ {_Name,_StartCmd,_ChkUp,StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config),
+ StopCommand(?config(ftpd_start_result,Config)).
+
+ps_ftpd(Config) ->
+ {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config),
+ ct:log( ChkUp(?config(ftpd_start_result,Config)) ).
+
+
+ftpd_running(Config) ->
+ {_Name,_StartCmd,ChkUp,_StopCommand,_ConfigUpd,_Host,_Port} = ?config(ftpd_data, Config),
+ ChkUp(?config(ftpd_start_result,Config)).
+
+%%--------------------------------------------------------------------
+%% start/stop of ftpc
+%%
+ftp__open(Config, Options) ->
+ Host = ?config(ftpd_host,Config),
+ Port = ?config(ftpd_port,Config),
+ ct:log("Host=~p, Port=~p",[Host,Port]),
+ {ok,Pid} = ftp:open(Host, [{port,Port} | Options]),
+ [{ftp,Pid}|Config].
+
+ftp__close(Config) ->
+ ok = ftp:close(?config(ftp,Config)),
Config.
%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
+%%
+split(Cs) -> string:tokens(Cs, "\r\n").
+
+%%--------------------------------------------------------------------
+%%
+find_diff(Bin1, Bin2) ->
+ case find_diff(Bin1, Bin2, 1) of
+ {error, {diff,Pos,RC,LC}} ->
+ ct:log("Contents differ at position ~p.~nOp1: ~p~nOp2: ~p",[Pos,RC,LC]),
+ ct:fail("Contents differ at pos ~p",[Pos]);
+ Other ->
+ Other
+ end.
+
+find_diff(A, A, _) -> true;
+find_diff(<<H,T1/binary>>, <<H,T2/binary>>, Pos) -> find_diff(T1, T2, Pos+1);
+find_diff(RC, LC, Pos) -> {error, {diff, Pos, RC, LC}}.
%%--------------------------------------------------------------------
-end_per_suite(_Config) ->
- inets:stop(),
- ok.
+%%
+set_state(Ops, Config) when is_list(Ops) -> lists:foldl(fun set_state/2, Config, Ops);
+
+set_state(reset, Config) ->
+ rm('*', id2abs("",Config)),
+ PrivDir = ?config(priv_dir,Config),
+ file:set_cwd(PrivDir),
+ ftp:lcd(?config(ftp,Config),PrivDir),
+ set_state({mkdir,""},Config);
+set_state({mkdir,Id}, Config) ->
+ Abs = id2abs(Id, Config),
+ mk_path(Abs),
+ file:make_dir(Abs),
+ Config;
+set_state({mkfile,Id,Contents}, Config) ->
+ Abs = id2abs(Id, Config),
+ mk_path(Abs),
+ ok = file:write_file(Abs, Contents),
+ Config.
+
+mk_path(Abs) -> lists:foldl(fun mk_path/2, [], filename:split(filename:dirname(Abs))).
+
+mk_path(F, Pfx) ->
+ case file:read_file_info(AbsName=filename:join(Pfx,F)) of
+ {ok,#file_info{type=directory}} ->
+ AbsName;
+ {error,eexist} ->
+ AbsName;
+ {error,enoent} ->
+ ok = file:make_dir(AbsName),
+ AbsName
+ end.
+
+
+rm('*', Pfx) ->
+ {ok,Fs} = file:list_dir(Pfx),
+ lists:foreach(fun(F) -> rm(F, Pfx) end, Fs);
+rm(F, Pfx) ->
+ case file:read_file_info(AbsName=filename:join(Pfx,F)) of
+ {ok,#file_info{type=directory}} ->
+ {ok,Fs} = file:list_dir(AbsName),
+ lists:foreach(fun(F1) -> rm(F1,AbsName) end, Fs),
+ ok = file:del_dir(AbsName);
+
+ {ok,#file_info{type=regular}} ->
+ ok = file:delete(AbsName);
+
+ {error,enoent} ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+%%
+
+id2abs(Id, Conf) -> filename:join(?config(priv_dir,Conf),ids(Id)).
+id2ftp(Id, Conf) -> (?config(id2ftp,Conf))(ids(Id)).
+id2ftp_result(Id, Conf) -> (?config(id2ftp_result,Conf))(ids(Id)).
+
+ids([[_|_]|_]=Ids) -> filename:join(Ids);
+ids(Id) -> Id.
+
+
+is_expected_absName(Id, File, Conf) -> File = (?config(id2abs,Conf))(Id).
+is_expected_ftpInName(Id, File, Conf) -> File = (?config(id2ftp,Conf))(Id).
+is_expected_ftpOutName(Id, File, Conf) -> File = (?config(id2ftp_result,Conf))(Id).
diff --git a/lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel b/lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel
index 75096ce687..98dff81881 100644
--- a/lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel
+++ b/lib/inets/test/ftp_SUITE_data/ftpd_hosts.skel
@@ -1,13 +1,13 @@
%% Add a host name in the appropriate list
-%% Each "platform" contains a list of hostnames (a string) that can
+%% Each "platform" contains a list of hostnames (a string) that can
%% be used for testing the ftp client.
%% The definition below are an example!!
-[{solaris8_sparc, ["solaris8_sparc_dummy1", "solaris8_sparc_dummy2"]},
- {solaris9_sparc, ["solaris9_sparc_dummy1"]},
- {solaris10_sparc, ["solaris10_sparc_dummy1"]},
- {solaris10_x86, ["solaris10_x86_dummy1", "solaris10_x86_dummy2"]},
- {linux_x86, ["linux_x86_dummy1", "linux_x86_dummy2"]},
- {linux_ppc, ["linux_ppc_dummy1"]},
+[{solaris8_sparc, ["solaris8_sparc_dummy1", "solaris8_sparc_dummy2"]},
+ {solaris9_sparc, ["solaris9_sparc_dummy1"]},
+ {solaris10_sparc, ["solaris10_sparc_dummy1"]},
+ {solaris10_x86, ["solaris10_x86_dummy1", "solaris10_x86_dummy2"]},
+ {linux_x86, ["linux_x86_dummy1", "linux_x86_dummy2"]},
+ {linux_ppc, ["linux_ppc_dummy1"]},
{macosx_ppc, ["macosx_ppc_dummy1"]},
{macosx_x86, ["macosx_x86_dummy1", "macosx_x86_dummy2"]},
{openbsd_x86, []},
diff --git a/lib/inets/test/ftp_SUITE_data/vsftpd.conf b/lib/inets/test/ftp_SUITE_data/vsftpd.conf
new file mode 100644
index 0000000000..11c96ad016
--- /dev/null
+++ b/lib/inets/test/ftp_SUITE_data/vsftpd.conf
@@ -0,0 +1,26 @@
+
+###
+### Some parameters are given in the vsftpd start command.
+###
+### Typical command-line paramters are such that has a file path
+### component like cert files.
+###
+
+
+listen=YES
+listen_port=9999
+run_as_launching_user=YES
+ssl_enable=YES
+allow_anon_ssl=YES
+
+background=YES
+
+write_enable=YES
+anonymous_enable=YES
+anon_upload_enable=YES
+anon_mkdir_write_enable=YES
+anon_other_write_enable=YES
+anon_world_readable_only=NO
+
+### Shouldn't be necessary....
+require_ssl_reuse=NO
diff --git a/lib/inets/test/ftp_format_SUITE.erl b/lib/inets/test/ftp_format_SUITE.erl
index cbc1b04bbb..02b9000dd9 100644
--- a/lib/inets/test/ftp_format_SUITE.erl
+++ b/lib/inets/test/ftp_format_SUITE.erl
@@ -273,7 +273,7 @@ ftp_other_status_codes(Config) when is_list(Config) ->
%% 4XX
{trans_neg_compl, _ } = ftp_response:interpret("421 Foobar\r\n"),
{trans_neg_compl, _ } = ftp_response:interpret("426 Foobar\r\n"),
- {trans_neg_compl, _ } = ftp_response:interpret("450 Foobar\r\n"),
+ {enofile, _ } = ftp_response:interpret("450 Foobar\r\n"),
{trans_neg_compl, _ } = ftp_response:interpret("451 Foobar\r\n"),
{etnospc, _ } = ftp_response:interpret("452 Foobar\r\n"),
diff --git a/lib/inets/test/ftp_freebsd_x86_test.erl b/lib/inets/test/ftp_freebsd_x86_test.erl
deleted file mode 100644
index 1d66779882..0000000000
--- a/lib/inets/test/ftp_freebsd_x86_test.erl
+++ /dev/null
@@ -1,160 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_freebsd_x86_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Freebsd x86 ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(freebsd_x86, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_linux_ppc_test.erl b/lib/inets/test/ftp_linux_ppc_test.erl
deleted file mode 100644
index bba97237f1..0000000000
--- a/lib/inets/test/ftp_linux_ppc_test.erl
+++ /dev/null
@@ -1,158 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_linux_ppc_test).
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Linux ppc ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(linux_ppc, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
diff --git a/lib/inets/test/ftp_linux_x86_test.erl b/lib/inets/test/ftp_linux_x86_test.erl
deleted file mode 100644
index bbefd8231e..0000000000
--- a/lib/inets/test/ftp_linux_x86_test.erl
+++ /dev/null
@@ -1,160 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_linux_x86_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Linux x86 ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(linux_x86, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_macosx_ppc_test.erl b/lib/inets/test/ftp_macosx_ppc_test.erl
deleted file mode 100644
index c9f33b8beb..0000000000
--- a/lib/inets/test/ftp_macosx_ppc_test.erl
+++ /dev/null
@@ -1,159 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_macosx_ppc_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Macosx ppc ").
-
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(macosx_ppc, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
-[open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(_X) -> {skipped,"unknown error"}.%?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(_X) -> {skipped,"unknown error"}.%%?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_macosx_x86_test.erl b/lib/inets/test/ftp_macosx_x86_test.erl
deleted file mode 100644
index 17b7160b95..0000000000
--- a/lib/inets/test/ftp_macosx_x86_test.erl
+++ /dev/null
@@ -1,159 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_macosx_x86_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Macosx x86 ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(macosx_x86, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
-[open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist([{wildcard_support, false} | X]).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist([{wildcard_support, false} | X]).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_netbsd_x86_test.erl b/lib/inets/test/ftp_netbsd_x86_test.erl
deleted file mode 100644
index bb474852c5..0000000000
--- a/lib/inets/test/ftp_netbsd_x86_test.erl
+++ /dev/null
@@ -1,159 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_netbsd_x86_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Netbsd x86 ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(netbsd_x86, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_openbsd_x86_test.erl b/lib/inets/test/ftp_openbsd_x86_test.erl
deleted file mode 100644
index 54fce702a0..0000000000
--- a/lib/inets/test/ftp_openbsd_x86_test.erl
+++ /dev/null
@@ -1,158 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_openbsd_x86_test).
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Openbsd x86 ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(openbsd_x86, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
diff --git a/lib/inets/test/ftp_solaris10_sparc_test.erl b/lib/inets/test/ftp_solaris10_sparc_test.erl
deleted file mode 100644
index 0da50dc91b..0000000000
--- a/lib/inets/test/ftp_solaris10_sparc_test.erl
+++ /dev/null
@@ -1,161 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_solaris10_sparc_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Solaris 10 sparc ").
-
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(solaris10_sparc, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_solaris10_x86_test.erl b/lib/inets/test/ftp_solaris10_x86_test.erl
deleted file mode 100644
index 3e7045bb4d..0000000000
--- a/lib/inets/test/ftp_solaris10_x86_test.erl
+++ /dev/null
@@ -1,162 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_solaris10_x86_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD, ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_), ?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM, "Solaris 10 x86 ").
-
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(solaris10_x86, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-%%--------------------------------------------------------------------
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_solaris8_sparc_test.erl b/lib/inets/test/ftp_solaris8_sparc_test.erl
deleted file mode 100644
index 23dbfc8fe3..0000000000
--- a/lib/inets/test/ftp_solaris8_sparc_test.erl
+++ /dev/null
@@ -1,159 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_solaris8_sparc_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Solaris 8 sparc ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(solaris8_sparc, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_solaris9_sparc_test.erl b/lib/inets/test/ftp_solaris9_sparc_test.erl
deleted file mode 100644
index 896e2f497f..0000000000
--- a/lib/inets/test/ftp_solaris9_sparc_test.erl
+++ /dev/null
@@ -1,158 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_solaris9_sparc_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Solaris 9 sparc ").
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(solaris9_sparc, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index ffb58c91b6..172270e3f1 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
@@ -47,17 +47,17 @@
-define(BAD_DIR, "baddirectory").
-ifdef(ftp_debug_client).
--define(ftp_open(Host, Flags),
- do_ftp_open(Host, [{debug, debug},
+-define(ftp_open(Host, Flags),
+ do_ftp_open(Host, [{debug, debug},
{timeout, timer:seconds(15)} | Flags])).
-else.
-ifdef(ftp_trace_client).
--define(ftp_open(Host, Flags),
- do_ftp_open(Host, [{debug, trace},
+-define(ftp_open(Host, Flags),
+ do_ftp_open(Host, [{debug, trace},
{timeout, timer:seconds(15)} | Flags])).
-else.
--define(ftp_open(Host, Flags),
- do_ftp_open(Host, [{verbose, true},
+-define(ftp_open(Host, Flags),
+ do_ftp_open(Host, [{verbose, true},
{timeout, timer:seconds(15)} | Flags])).
-endif.
-endif.
@@ -73,7 +73,7 @@ tickets(suite) ->
ftpd_init(FtpdTag, Config) ->
%% Get the host name(s) of FTP server
- Hosts =
+ Hosts =
case ct:get_config(ftpd_hosts) of
undefined ->
ftpd_hosts(data_dir(Config));
@@ -96,7 +96,7 @@ ftpd_init(FtpdTag, Config) ->
inets:stop(),
Reason = lists:flatten(
io_lib:format("Could not find a valid "
- "FTP server for ~p (~p)",
+ "FTP server for ~p (~p)",
[FtpdTag, TagHosts])),
{skip, Reason}
end;
@@ -110,9 +110,9 @@ ftpd_init(FtpdTag, Config) ->
ftpd_fin(Config) ->
lists:keydelete(ftp_remote_host, 1, Config).
-get_ftpd_host([]) ->
+get_ftpd_host([]) ->
{error, no_host};
-get_ftpd_host([Host|Hosts]) ->
+get_ftpd_host([Host|Hosts]) ->
p("get_ftpd_host -> entry with"
"~n Host: ~p"
"~n", [Host]),
@@ -128,7 +128,7 @@ get_ftpd_host([Host|Hosts]) ->
%%--------------------------------------------------------------------
dirty_select_ftpd_host(Config) ->
- Hosts =
+ Hosts =
case ct:get_config(ftpd_hosts) of
undefined ->
ftpd_hosts(data_dir(Config));
@@ -159,11 +159,11 @@ dirty_select_ftpd_host3([Host|Hosts]) when is_list(Host) ->
dirty_select_ftpd_host3([_|Hosts]) ->
dirty_select_ftpd_host3(Hosts).
-%% This is a very simple and dirty test that there is a
+%% This is a very simple and dirty test that there is a
%% (FTP) deamon on the other end.
dirty_select_ftpd_host4(Host) ->
- Port = 21,
- IpFam = inet,
+ Port = 21,
+ IpFam = inet,
Opts = [IpFam, binary, {packet, 0}, {active, false}],
Timeout = ?SECS(5),
case gen_tcp:connect(Host, Port, Opts, Timeout) of
@@ -195,26 +195,25 @@ test_filenames() ->
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
-init_per_testcase(Case, Config)
- when (Case =:= open) orelse
+init_per_testcase(Case, Config)
+ when (Case =:= open) orelse
(Case =:= open_port) ->
- put(ftp_testcase, Case),
+ put(ftp_testcase, Case),
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
inets:start(),
NewConfig = data_dir(Config),
watch_dog(NewConfig);
init_per_testcase(Case, Config) ->
- put(ftp_testcase, Case),
- inets:enable_trace(max, io, ftpc),
+ put(ftp_testcase, Case),
do_init_per_testcase(Case, Config).
-do_init_per_testcase(Case, Config)
+do_init_per_testcase(Case, Config)
when (Case =:= passive_user) ->
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]),
inets:start(),
NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
+ Host = ftp_host(Config),
case (catch ?ftp_open(Host, [{mode, passive}])) of
{ok, Pid} ->
[{ftp, Pid} | data_dir(NewConfig)];
@@ -222,12 +221,12 @@ do_init_per_testcase(Case, Config)
SKIP
end;
-do_init_per_testcase(Case, Config)
+do_init_per_testcase(Case, Config)
when (Case =:= active_user) ->
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
inets:start(),
NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
+ Host = ftp_host(Config),
case (catch ?ftp_open(Host, [{mode, active}])) of
{ok, Pid} ->
[{ftp, Pid} | data_dir(NewConfig)];
@@ -235,16 +234,16 @@ do_init_per_testcase(Case, Config)
SKIP
end;
-do_init_per_testcase(Case, Config)
- when (Case =:= progress_report_send) orelse
+do_init_per_testcase(Case, Config)
+ when (Case =:= progress_report_send) orelse
(Case =:= progress_report_recv) ->
inets:start(),
io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
+ Host = ftp_host(Config),
Opts = [{port, ?FTP_PORT},
{verbose, true},
- {progress, {?MODULE, progress, #progress{}}}],
+ {progress, {?MODULE, progress, #progress{}}}],
case ftp:open(Host, Opts) of
{ok, Pid} ->
ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS),
@@ -257,16 +256,16 @@ do_init_per_testcase(Case, Config) ->
io:format(user,"~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]),
inets:start(),
NewConfig = close_connection(watch_dog(Config)),
- Host = ftp_host(Config),
- Opts1 =
- if
+ Host = ftp_host(Config),
+ Opts1 =
+ if
((Case =:= passive_ip_v6_disabled) orelse
(Case =:= active_ip_v6_disabled)) ->
- [{ipfamily, inet}];
- true ->
- []
- end,
- Opts2 =
+ [{ipfamily, inet}];
+ true ->
+ []
+ end,
+ Opts2 =
case string:tokens(atom_to_list(Case), [$_]) of
["active" | _] ->
[{mode, active} | Opts1];
@@ -290,7 +289,7 @@ do_init_per_testcase(Case, Config) ->
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
-end_per_testcase(_, Config) ->
+end_per_testcase(_, Config) ->
NewConfig = close_connection(Config),
Dog = ?config(watchdog, NewConfig),
inets:stop(),
@@ -304,51 +303,51 @@ end_per_testcase(_, Config) ->
passive(suite) ->
[
- passive_user,
- passive_pwd,
- passive_cd,
+ passive_user,
+ passive_pwd,
+ passive_cd,
passive_lcd,
- passive_ls,
- passive_nlist,
- passive_rename,
- passive_delete,
- passive_mkdir,
- passive_send,
- passive_send_bin,
- passive_send_chunk,
- passive_append,
+ passive_ls,
+ passive_nlist,
+ passive_rename,
+ passive_delete,
+ passive_mkdir,
+ passive_send,
+ passive_send_bin,
+ passive_send_chunk,
+ passive_append,
passive_append_bin,
- passive_append_chunk,
- passive_recv,
- passive_recv_bin,
- passive_recv_chunk,
- passive_type,
- passive_quote,
+ passive_append_chunk,
+ passive_recv,
+ passive_recv_bin,
+ passive_recv_chunk,
+ passive_type,
+ passive_quote,
passive_ip_v6_disabled
].
active(suite) ->
[
- active_user,
- active_pwd,
+ active_user,
+ active_pwd,
active_cd,
- active_lcd,
- active_ls,
- active_nlist,
- active_rename,
- active_delete,
- active_mkdir,
- active_send,
- active_send_bin,
- active_send_chunk,
- active_append,
- active_append_bin,
- active_append_chunk,
- active_recv,
- active_recv_bin,
- active_recv_chunk,
- active_type,
- active_quote,
+ active_lcd,
+ active_ls,
+ active_nlist,
+ active_rename,
+ active_delete,
+ active_mkdir,
+ active_send,
+ active_send_bin,
+ active_send_chunk,
+ active_append,
+ active_append_bin,
+ active_append_chunk,
+ active_recv,
+ active_recv_bin,
+ active_recv_chunk,
+ active_type,
+ active_quote,
active_ip_v6_disabled
].
@@ -364,7 +363,7 @@ open(doc) ->
open(suite) ->
[];
open(Config) when is_list(Config) ->
- Host = ftp_host(Config),
+ Host = ftp_host(Config),
(catch tc_open(Host)).
@@ -374,19 +373,19 @@ tc_open(Host) ->
{ok, Pid} = ?ftp_open(Host, []),
ok = ftp:close(Pid),
p("tc_open -> try (ok) open 1"),
- {ok, Pid1} =
- ftp:open({option_list, [{host,Host},
- {port, ?FTP_PORT},
- {flags, [verbose]},
+ {ok, Pid1} =
+ ftp:open({option_list, [{host,Host},
+ {port, ?FTP_PORT},
+ {flags, [verbose]},
{timeout, 30000}]}),
ok = ftp:close(Pid1),
-
+
p("tc_open -> try (fail) open 2"),
- {error, ehost} =
+ {error, ehost} =
ftp:open({option_list, [{port, ?FTP_PORT}, {flags, [verbose]}]}),
{ok, Pid2} = ftp:open(Host),
ok = ftp:close(Pid2),
-
+
p("tc_open -> try (ok) open 3"),
{ok, NewHost} = inet:getaddr(Host, inet),
{ok, Pid3} = ftp:open(NewHost),
@@ -397,82 +396,82 @@ tc_open(Host) ->
["200" ++ _] = ftp:quote(Pid3, "NOOP"),
ok = ftp:close(Pid3),
- %% Bad input that has default values are ignored and the defult
+ %% Bad input that has default values are ignored and the defult
%% is used.
p("tc_open -> try (ok) open 4"),
- {ok, Pid4} =
- ftp:open({option_list, [{host, Host},
- {port, badarg},
- {flags, [verbose]},
+ {ok, Pid4} =
+ ftp:open({option_list, [{host, Host},
+ {port, badarg},
+ {flags, [verbose]},
{timeout, 30000}]}),
test_server:sleep(100),
ok = ftp:close(Pid4),
p("tc_open -> try (ok) open 5"),
- {ok, Pid5} =
- ftp:open({option_list, [{host, Host},
- {port, ?FTP_PORT},
- {flags, [verbose]},
+ {ok, Pid5} =
+ ftp:open({option_list, [{host, Host},
+ {port, ?FTP_PORT},
+ {flags, [verbose]},
{timeout, -42}]}),
test_server:sleep(100),
ok = ftp:close(Pid5),
p("tc_open -> try (ok) open 6"),
- {ok, Pid6} =
- ftp:open({option_list, [{host, Host},
- {port, ?FTP_PORT},
- {flags, [verbose]},
+ {ok, Pid6} =
+ ftp:open({option_list, [{host, Host},
+ {port, ?FTP_PORT},
+ {flags, [verbose]},
{mode, cool}]}),
test_server:sleep(100),
ok = ftp:close(Pid6),
p("tc_open -> try (ok) open 7"),
- {ok, Pid7} =
+ {ok, Pid7} =
ftp:open(Host, [{port, ?FTP_PORT}, {verbose, true}, {timeout, 30000}]),
ok = ftp:close(Pid7),
p("tc_open -> try (ok) open 8"),
- {ok, Pid8} =
+ {ok, Pid8} =
ftp:open(Host, ?FTP_PORT),
ok = ftp:close(Pid8),
p("tc_open -> try (ok) open 9"),
- {ok, Pid9} =
- ftp:open(Host, [{port, ?FTP_PORT},
- {verbose, true},
- {timeout, 30000},
+ {ok, Pid9} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
{dtimeout, -99}]),
ok = ftp:close(Pid9),
p("tc_open -> try (ok) open 10"),
- {ok, Pid10} =
- ftp:open(Host, [{port, ?FTP_PORT},
- {verbose, true},
- {timeout, 30000},
+ {ok, Pid10} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
{dtimeout, "foobar"}]),
ok = ftp:close(Pid10),
p("tc_open -> try (ok) open 11"),
- {ok, Pid11} =
- ftp:open(Host, [{port, ?FTP_PORT},
- {verbose, true},
- {timeout, 30000},
+ {ok, Pid11} =
+ ftp:open(Host, [{port, ?FTP_PORT},
+ {verbose, true},
+ {timeout, 30000},
{dtimeout, 1}]),
ok = ftp:close(Pid11),
p("tc_open -> done"),
ok.
-
+
%%-------------------------------------------------------------------------
open_port(doc) ->
["Open an ftp connection to a host with given port number "
- "and close the connection."]; % See also OTP-3892
+ "and close the connection."]; % See also OTP-3892
open_port(suite) ->
[];
open_port(Config) when is_list(Config) ->
- Host = ftp_host(Config),
+ Host = ftp_host(Config),
{ok, Pid} = ftp:open(Host, [{port, ?FTP_PORT}]),
ok = ftp:close(Pid),
{error, ehost} = ftp:open(?BAD_HOST, []),
@@ -492,7 +491,7 @@ passive_user(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
-
+
passive_pwd(doc) ->
["Test ftp:pwd/1 & ftp:lpwd/1"];
passive_pwd(suite) ->
@@ -563,7 +562,7 @@ passive_rename(suite) ->
passive_rename(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_rename(Pid, Config).
-
+
%%-------------------------------------------------------------------------
@@ -574,7 +573,7 @@ passive_delete(suite) ->
passive_delete(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_delete(Pid, Config).
-
+
%%-------------------------------------------------------------------------
@@ -586,7 +585,7 @@ passive_mkdir(suite) ->
passive_mkdir(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_mkdir(Pid).
-
+
%%-------------------------------------------------------------------------
@@ -618,9 +617,9 @@ passive_append(suite) ->
passive_append(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_append(Pid, Config).
-
-%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
passive_send_bin(doc) ->
["Open a connection to a host; cd to the directory \"incoming\"; "
@@ -644,7 +643,7 @@ passive_append_bin(Config) when is_list(Config) ->
do_append_bin(Pid, Config).
-%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
passive_send_chunk(doc) ->
["Open a connection to a host; cd to the directory \"incoming\"; "
@@ -682,7 +681,7 @@ passive_recv(suite) ->
passive_recv(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_recv(Pid, Config).
-
+
%%-------------------------------------------------------------------------
@@ -824,7 +823,7 @@ active_rename(suite) ->
active_rename(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_rename(Pid, Config).
-
+
%%-------------------------------------------------------------------------
@@ -835,7 +834,7 @@ active_delete(suite) ->
active_delete(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_delete(Pid, Config).
-
+
%%-------------------------------------------------------------------------
@@ -847,7 +846,7 @@ active_mkdir(suite) ->
active_mkdir(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_mkdir(Pid).
-
+
%%-------------------------------------------------------------------------
@@ -879,9 +878,9 @@ active_append(suite) ->
active_append(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_append(Pid, Config).
-
-%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
active_send_bin(doc) ->
["Open a connection to a host; cd to the directory \"incoming\"; "
@@ -906,7 +905,7 @@ active_append_bin(Config) when is_list(Config) ->
do_append_bin(Pid, Config).
-%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
active_send_chunk(doc) ->
["Open a connection to a host; cd to the directory \"incoming\"; "
@@ -944,7 +943,7 @@ active_recv(suite) ->
active_recv(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
do_recv(Pid, Config).
-
+
%%-------------------------------------------------------------------------
@@ -1012,9 +1011,9 @@ api_missuse(Config) when is_list(Config) ->
p("api_missuse -> entry"),
Flag = process_flag(trap_exit, true),
Pid = ?config(ftp, Config),
- Host = ftp_host(Config),
-
- %% Serious programming fault, connetion will be shut down
+ Host = ftp_host(Config),
+
+ %% Serious programming fault, connetion will be shut down
p("api_missuse -> verify bad call termination (~p)", [Pid]),
case (catch gen_server:call(Pid, {self(), foobar, 10}, infinity)) of
{error, {connection_terminated, 'API_violation'}} ->
@@ -1027,7 +1026,7 @@ api_missuse(Config) when is_list(Config) ->
p("api_missuse -> start new client"),
{ok, Pid2} = ?ftp_open(Host, []),
- %% Serious programming fault, connetion will be shut down
+ %% Serious programming fault, connetion will be shut down
p("api_missuse -> verify bad cast termination"),
gen_server:cast(Pid2, {self(), foobar, 10}),
test_server:sleep(500),
@@ -1035,9 +1034,9 @@ api_missuse(Config) when is_list(Config) ->
p("api_missuse -> start new client"),
{ok, Pid3} = ?ftp_open(Host, []),
- %% Could be an innocent misstake the connection lives.
+ %% Could be an innocent misstake the connection lives.
p("api_missuse -> verify bad bang"),
- Pid3 ! foobar,
+ Pid3 ! foobar,
test_server:sleep(500),
{status, _} = process_info(Pid3, status),
process_flag(trap_exit, Flag),
@@ -1055,7 +1054,7 @@ not_owner(suite) ->
not_owner(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
OtherPid = spawn_link(?MODULE, not_owner, [Pid, self()]),
-
+
receive
{OtherPid, ok} ->
{ok, _} = ftp:pwd(Pid)
@@ -1078,7 +1077,7 @@ progress_report(suite) ->
[progress_report_send, progress_report_recv].
-%% --
+%% --
progress_report_send(doc) ->
["Test the option progress for ftp:send/[2,3]"];
@@ -1086,7 +1085,7 @@ progress_report_send(suite) ->
[];
progress_report_send(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
- ReportPid =
+ ReportPid =
spawn_link(?MODULE, progress_report_receiver_init, [self(), 1]),
do_send(Pid, Config),
receive
@@ -1095,7 +1094,7 @@ progress_report_send(Config) when is_list(Config) ->
end.
-%% --
+%% --
progress_report_recv(doc) ->
["Test the option progress for ftp:recv/[2,3]"];
@@ -1103,19 +1102,19 @@ progress_report_recv(suite) ->
[];
progress_report_recv(Config) when is_list(Config) ->
Pid = ?config(ftp, Config),
- ReportPid =
- spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
+ ReportPid =
+ spawn_link(?MODULE, progress_report_receiver_init, [self(), 3]),
do_recv(Pid, Config),
receive
- {ReportPid, ok} ->
- ok
+ {ReportPid, ok} ->
+ ok
end,
ok.
progress(#progress{} = Progress , _File, {file_size, Total}) ->
progress_report_receiver ! start,
Progress#progress{total = Total};
-progress(#progress{total = Total, current = Current}
+progress(#progress{total = Total, current = Current}
= Progress, _File, {transfer_size, 0}) ->
progress_report_receiver ! finish,
case Total of
@@ -1128,7 +1127,7 @@ progress(#progress{total = Total, current = Current}
{current, Current}}})
end,
Progress;
-progress(#progress{current = Current} = Progress, _File,
+progress(#progress{current = Current} = Progress, _File,
{transfer_size, Size}) ->
progress_report_receiver ! update,
Progress#progress{current = Current + Size}.
@@ -1172,10 +1171,10 @@ ticket_6035(Config) ->
try
begin
p("ticket_6035 -> select ftpd host"),
- Host = dirty_select_ftpd_host(Config),
+ Host = dirty_select_ftpd_host(Config),
p("ticket_6035 -> ftpd host selected (~p) => now spawn ftp owner", [Host]),
Pid = spawn(?MODULE, open_wait_6035, [Host, self()]),
- p("ticket_6035 -> waiter spawned: ~p => now open error logfile (~p)",
+ p("ticket_6035 -> waiter spawned: ~p => now open error logfile (~p)",
[Pid, LogFile]),
error_logger:logfile({open, LogFile}),
p("ticket_6035 -> error logfile open => now kill waiter process"),
@@ -1185,7 +1184,7 @@ ticket_6035(Config) ->
p("ticket_6035 -> done", []),
ok
end
- catch
+ catch
throw:{error, not_found} ->
{skip, "No available FTP servers"}
end.
@@ -1216,7 +1215,7 @@ open_wait_6035({Tag, FtpServer}, From) ->
p("open_wait_6035 -> login result: ~p", [LoginResult]),
From ! open,
receive
- dummy ->
+ dummy ->
p("open_wait_6035 -> received dummy"),
ok
after
@@ -1239,7 +1238,7 @@ is_error_report_6035(LogFile) ->
Res =
case file:read_file(LogFile) of
{ok, Bin} ->
- Txt = binary_to_list(Bin),
+ Txt = binary_to_list(Bin),
p("is_error_report_6035 -> logfile read: ~n~p", [Txt]),
read_log_6035(Txt);
_ ->
@@ -1291,8 +1290,8 @@ do_ls(Pid) ->
{ok, _} = ftp:ls(Pid),
{ok, _} = ftp:ls(Pid, "incoming"),
%% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
%% of files (including wildcards).
{ok, _} = ftp:ls(Pid, "incom*"),
ok.
@@ -1301,8 +1300,8 @@ do_nlist(Pid, WildcardSupport) ->
{ok, _} = ftp:nlist(Pid),
{ok, _} = ftp:nlist(Pid, "incoming"),
%% neither nlist nor ls operates on a directory
- %% they operate on a pathname, which *can* be a
- %% directory, but can also be a filename or a group
+ %% they operate on a pathname, which *can* be a
+ %% directory, but can also be a filename or a group
%% of files (including wildcards).
case WildcardSupport of
true ->
@@ -1323,7 +1322,7 @@ do_rename(Pid, Config) ->
ok = ftp:lcd(Pid, PrivDir),
ftp:delete(Pid, LFile), % reset
ftp:delete(Pid, NewLFile), % reset
- ok = ftp:send(Pid, LFile),
+ ok = ftp:send(Pid, LFile),
{error, epath} = ftp:rename(Pid, NewLFile, LFile),
ok = ftp:rename(Pid, LFile, NewLFile),
ftp:delete(Pid, LFile), % cleanup
@@ -1335,7 +1334,7 @@ do_delete(Pid, Config) ->
LFile = ?config(file, Config),
AbsLFile = filename:absname(LFile, PrivDir),
Contents = "ftp_SUITE test ...",
- ok = file:write_file(AbsLFile, list_to_binary(Contents)),
+ ok = file:write_file(AbsLFile, list_to_binary(Contents)),
ok = ftp:cd(Pid, "incoming"),
ok = ftp:lcd(Pid, PrivDir),
ftp:delete(Pid,LFile), % reset
@@ -1402,7 +1401,7 @@ do_append(Pid, Config) ->
ok = ftp:delete(Pid, RFile),
ok = file:delete(AbsLFile),
ok = check_content(binary_to_list(Bin1), Contents, double),
-
+
{ok, Bin2} = ftp:recv_bin(Pid, LFile),
ok = ftp:delete(Pid, LFile),
ok = check_content(binary_to_list(Bin2), Contents, singel),
@@ -1485,7 +1484,7 @@ do_recv(Pid, Config) ->
{ok, Files} = file:list_dir(PrivDir),
true = lists:member(File, Files),
ok = file:delete(AbsFile), % cleanup
- ok = ftp:recv(Pid, File, Newfile),
+ ok = ftp:recv(Pid, File, Newfile),
ok = ftp:delete(Pid, File), % cleanup
ok.
@@ -1539,8 +1538,8 @@ do_quote(Pid) ->
[_| _] = ftp:quote(Pid, "help"),
%% This negativ test causes some ftp servers to hang. This test
%% is not important for the client, so we skip it for now.
- %%["425 Can't build data connection: Connection refused."]
- %% = ftp:quote(Pid, "list"),
+ %%["425 Can't build data connection: Connection refused."]
+ %% = ftp:quote(Pid, "list"),
ok.
watch_dog(Config) ->
@@ -1550,23 +1549,23 @@ do_quote(Pid) ->
close_connection(Config) ->
case ?config(ftp, Config) of
- Pid when is_pid(Pid) ->
- ok = ftp:close(Pid),
- lists:delete({ftp, Pid}, Config);
- _ ->
- Config
+ Pid when is_pid(Pid) ->
+ ok = ftp:close(Pid),
+ lists:delete({ftp, Pid}, Config);
+ _ ->
+ Config
end.
-
+
ftp_host(Config) ->
case ?config(ftp_remote_host, Config) of
undefined ->
exit({skip, "No host specified"});
Host ->
- Host
+ Host
end.
check_content(RContent, LContent, Amount) ->
- LContent2 = case Amount of
+ LContent2 = case Amount of
double ->
LContent ++ LContent;
singel ->
@@ -1602,7 +1601,7 @@ split(Cs) ->
split(Cs, [], []).
split([$\r, $\n| Cs], I, Is) ->
- split(Cs, [], [lists:reverse(I)| Is]);
+ split(Cs, [], [lists:reverse(I)| Is]);
split([C| Cs], I, Is) ->
split(Cs, [C| I], Is);
split([], I, Is) ->
@@ -1611,21 +1610,21 @@ split([], I, Is) ->
do_ftp_open(Host, Opts) ->
p("do_ftp_open -> entry with"
"~n Host: ~p"
- "~n Opts: ~p", [Host, Opts]),
+ "~n Opts: ~p", [Host, Opts]),
case ftp:open(Host, Opts) of
{ok, _} = OK ->
OK;
{error, Reason} ->
- Str =
+ Str =
lists:flatten(
- io_lib:format("Unable to reach test FTP server ~p (~p)",
+ io_lib:format("Unable to reach test FTP server ~p (~p)",
[Host, Reason])),
throw({skip, Str})
end.
-
+
passwd() ->
- Host =
+ Host =
case inet:gethostname() of
{ok, H} ->
H;
@@ -1641,7 +1640,7 @@ ftpd_hosts(Config) ->
case file:consult(FileName) of
{ok, [Hosts]} when is_list(Hosts) ->
Hosts;
- _ ->
+ _ ->
[]
end.
@@ -1656,14 +1655,14 @@ data_dir(Config) ->
PathList = filename:split(List),
{NewPathList,_} = lists:split((length(PathList)-1), PathList),
DataDir = filename:join(NewPathList ++ [ftp_SUITE_data]),
- NewConfig =
+ NewConfig =
lists:keyreplace(data_dir,1,Config, {data_dir,DataDir}),
NewConfig;
_ -> Config
end.
-
-
-
+
+
+
p(F) ->
p(F, []).
diff --git a/lib/inets/test/ftp_ticket_test.erl b/lib/inets/test/ftp_ticket_test.erl
deleted file mode 100644
index fe4ab35728..0000000000
--- a/lib/inets/test/ftp_ticket_test.erl
+++ /dev/null
@@ -1,61 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_ticket_test).
-
--compile(export_all).
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Solaris 8 sparc ").
-
-
-%% Test server callbacks
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-
-all() ->
- tickets().
-
-groups() ->
- [].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-init_per_suite(Config) ->
- ?LIB_MOD:ftpd_init(ticket_test, Config).
-
-tickets() ->
- [ticket_6035].
-
-
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-ticket_6035(X) -> ?LIB_MOD:ticket_6035(X).
diff --git a/lib/inets/test/ftp_windows_2003_server_test.erl b/lib/inets/test/ftp_windows_2003_server_test.erl
deleted file mode 100644
index 32f25713f8..0000000000
--- a/lib/inets/test/ftp_windows_2003_server_test.erl
+++ /dev/null
@@ -1,167 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_windows_2003_server_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Windows 2003 server ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(windows_2003_server, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [
- open,
- open_port,
- {group, passive},
- {group, active},
- api_missuse,
- not_owner,
- {group, progress_report}
- ].
-
-groups() ->
- [
- {passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [], ftp_suite_lib:progress_report(suite)}
- ].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%% Test cases starts here.
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/ftp_windows_xp_test.erl b/lib/inets/test/ftp_windows_xp_test.erl
deleted file mode 100644
index 06d919ba00..0000000000
--- a/lib/inets/test/ftp_windows_xp_test.erl
+++ /dev/null
@@ -1,157 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(ftp_windows_xp_test).
-
--compile(export_all).
-
--include_lib("common_test/include/ct.hrl").
-
--define(LIB_MOD,ftp_suite_lib).
--define(CASE_WRAPPER(_A_,_B_,_C_),?LIB_MOD:wrapper(_A_,_B_,_C_)).
--define(PLATFORM,"Windows xp ").
-
-%% Test server callback functions
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
- {File, NewFile} = ?LIB_MOD:test_filenames(),
- NewConfig = [{file, File}, {new_file, NewFile} | Config],
- ?LIB_MOD:ftpd_init(windows_xp, NewConfig).
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(TestCase, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%% Description: Initiation before each test case
-%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- ftp_suite_lib:init_per_testcase(Case, Config).
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(TestCase, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- ftp_suite_lib:end_per_testcase(Case, Config).
-
-%%--------------------------------------------------------------------
-%% Function: all(Clause) -> TestCases
-%% Clause - atom() - suite | doc
-%% TestCases - [Case]
-%% Case - atom()
-%% Name of a test case.
-%% Description: Returns a list of all test cases in this test suite
-%%--------------------------------------------------------------------
-all() ->
- [open, open_port, {group, passive}, {group, active},
- api_missuse, not_owner, {group, progress_report}].
-
-groups() ->
- [{passive, [], ftp_suite_lib:passive(suite)},
- {active, [], ftp_suite_lib:active(suite)},
- {progress_report, [],
- ftp_suite_lib:progress_report(suite)}].
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-open(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open/1).
-open_port(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:open_port/1).
-api_missuse(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:api_missuse/1).
-not_owner(X) -> ?CASE_WRAPPER(?PLATFORM,X,fun ?LIB_MOD:not_owner/1).
-
-passive_user(X) -> ?LIB_MOD:passive_user(X).
-passive_pwd(X) -> ?LIB_MOD:passive_pwd(X).
-passive_cd(X) -> ?LIB_MOD:passive_cd(X).
-passive_lcd(X) -> ?LIB_MOD:passive_lcd(X).
-passive_ls(X) -> ?LIB_MOD:passive_ls(X).
-passive_nlist(X) -> ?LIB_MOD:passive_nlist(X).
-passive_rename(X) -> ?LIB_MOD:passive_rename(X).
-passive_delete(X) -> ?LIB_MOD:passive_delete(X).
-passive_mkdir(X) -> ?LIB_MOD:passive_mkdir(X).
-passive_send(X) -> ?LIB_MOD:passive_send(X).
-passive_send_bin(X) -> ?LIB_MOD:passive_send_bin(X).
-passive_send_chunk(X) -> ?LIB_MOD:passive_send_chunk(X).
-passive_append(X) -> ?LIB_MOD:passive_append(X).
-passive_append_bin(X) -> ?LIB_MOD:passive_append_bin(X).
-passive_append_chunk(X) -> ?LIB_MOD:passive_append_chunk(X).
-passive_recv(X) -> ?LIB_MOD:passive_recv(X).
-passive_recv_bin(X) -> ?LIB_MOD:passive_recv_bin(X).
-passive_recv_chunk(X) -> ?LIB_MOD:passive_recv_chunk(X).
-passive_type(X) -> ?LIB_MOD:passive_type(X).
-passive_quote(X) -> ?LIB_MOD:passive_quote(X).
-passive_ip_v6_disabled(X) -> ?LIB_MOD:passive_ip_v6_disabled(X).
-active_user(X) -> ?LIB_MOD:active_user(X).
-active_pwd(X) -> ?LIB_MOD:active_pwd(X).
-active_cd(X) -> ?LIB_MOD:active_cd(X).
-active_lcd(X) -> ?LIB_MOD:active_lcd(X).
-active_ls(X) -> ?LIB_MOD:active_ls(X).
-active_nlist(X) -> ?LIB_MOD:active_nlist(X).
-active_rename(X) -> ?LIB_MOD:active_rename(X).
-active_delete(X) -> ?LIB_MOD:active_delete(X).
-active_mkdir(X) -> ?LIB_MOD:active_mkdir(X).
-active_send(X) -> ?LIB_MOD:active_send(X).
-active_send_bin(X) -> ?LIB_MOD:active_send_bin(X).
-active_send_chunk(X) -> ?LIB_MOD:active_send_chunk(X).
-active_append(X) -> ?LIB_MOD:active_append(X).
-active_append_bin(X) -> ?LIB_MOD:active_append_bin(X).
-active_append_chunk(X) -> ?LIB_MOD:active_append_chunk(X).
-active_recv(X) -> ?LIB_MOD:active_recv(X).
-active_recv_bin(X) -> ?LIB_MOD:active_recv_bin(X).
-active_recv_chunk(X) -> ?LIB_MOD:active_recv_chunk(X).
-active_type(X) -> ?LIB_MOD:active_type(X).
-active_quote(X) -> ?LIB_MOD:active_quote(X).
-active_ip_v6_disabled(X) -> ?LIB_MOD:active_ip_v6_disabled(X).
-progress_report_send(X) -> ?LIB_MOD:progress_report_send(X).
-progress_report_recv(X) -> ?LIB_MOD:progress_report_recv(X).
-
-fin(Config) ->
- ?LIB_MOD:ftpd_fin(Config).
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index 04c7358715..c913964094 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -35,14 +35,15 @@
chunk_decode_trailer/1,
http_response/1, http_request/1, validate_request_line/1,
esi_parse_headers/1, cgi_parse_headers/1,
- is_absolut_uri/1, convert_netscapecookie_date/1]).
+ is_absolut_uri/1, convert_netscapecookie_date/1,
+ check_content_length_encoding/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[{group, chunk}, http_response, http_request,
validate_request_line, {group, script}, is_absolut_uri,
- convert_netscapecookie_date].
+ convert_netscapecookie_date, check_content_length_encoding].
groups() ->
[{script, [], [esi_parse_headers, cgi_parse_headers]},
@@ -456,6 +457,25 @@ validate_request_line(Config) when is_list(Config) ->
httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1"),
ok.
+
+%%-------------------------------------------------------------------------
+check_content_length_encoding(doc) ->
+ ["Test http_request:headers/2. Check that the content-length is"
+ " encoded even when it is zero." ];
+check_content_length_encoding(suite) ->
+ [];
+check_content_length_encoding(Config) when is_list(Config) ->
+
+ %% Check that the content-length is preserved.
+ %% Sanity check.
+ Header1 = http_request:http_headers(#http_request_h{'content-length'="123"}),
+ true = (string:str(Header1, "content-length: 123\r\n") > 0),
+ %% Check that content-length=0 is handled correctly.
+ Header2 = http_request:http_headers(#http_request_h{'content-length'="0"}),
+ true = (string:str(Header2, "content-length: 0\r\n") > 0),
+
+ ok.
+
%%-------------------------------------------------------------------------
esi_parse_headers(doc) ->
["Test httpd_esi:*. All header values are received in the same"
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 1cdd96f0b0..50025b1d9d 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,3057 +19,961 @@
%%
%%
-%% ts:run(inets, httpc_SUITE, [batch]).
-%%
+%% ct:run("../inets_test", httpc_SUITE).
+%%
-module(httpc_SUITE).
--include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-
-include_lib("kernel/include/file.hrl").
+-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
-%% Test server specific exports
--define(PROXY_URL, "http://www.erlang.org").
--define(PROXY, "www-proxy.ericsson.se").
--define(PROXY_PORT, 8080).
--define(IP_PORT, 8998).
--define(SSL_PORT, 8999).
+-define(URL_START, "http://").
+-define(TLS_URL_START, "https://").
-define(NOT_IN_USE_PORT, 8997).
--define(LOCAL_HOST, {127,0,0,1}).
--define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1").
--define(URL_START, "http://localhost:").
--define(SSL_URL_START, "https://localhost:").
--define(CR, $\r).
-define(LF, $\n).
-define(HTTP_MAX_HEADER_SIZE, 10240).
-
-
+-record(sslsocket, {fd = nil, pid = nil}).
%%--------------------------------------------------------------------
-%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
-%% Arg - doc | suite
-%% Doc - string()
-%% Case - atom()
-%% Name of a test case function.
-%% Comment - string()
-%% Description: Returns documentation/test cases in this test suite
-%% or a skip tuple if the platform is not supported.
+%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
+all() ->
[
- http_options,
- http_head,
- http_get,
- http_post,
- http_post_streaming,
- http_dummy_pipe,
- http_inets_pipe,
- http_trace,
- http_async,
- http_save_to_file,
- http_save_to_file_async,
- http_headers,
- http_headers_dummy,
- http_bad_response,
- http_redirect,
- http_redirect_loop,
- http_internal_server_error,
- http_userinfo, http_cookie,
- http_server_does_not_exist,
- http_invalid_http,
- http_emulate_lower_versions,
- http_relaxed,
- page_does_not_exist,
- parse_url,
- options,
- headers_as_is,
- selecting_session,
- {group, proxy},
- {group, ssl},
- {group, stream},
- {group, ipv6},
- {group, tickets},
- initial_server_connect
+ {group, http},
+ {group, sim_http},
+ {group, https},
+ {group, sim_https},
+ {group, misc}
].
-groups() ->
+groups() ->
[
- {proxy, [], [proxy_options,
- proxy_head,
- proxy_get,
- proxy_trace,
- proxy_post,
- proxy_put,
- proxy_delete,
- proxy_auth,
- proxy_headers,
- proxy_emulate_lower_versions,
- proxy_page_does_not_exist,
- proxy_https_not_supported]},
- {ssl, [], [ssl_head,
- essl_head,
- ssl_get,
- essl_get,
- ssl_trace,
- essl_trace]},
- {stream, [], [http_stream,
- http_stream_once,
- proxy_stream]},
- {tickets, [], [hexed_query_otp_6191,
- empty_body_otp_6243,
- empty_response_header_otp_6830,
- transfer_encoding_otp_6807,
- proxy_not_modified_otp_6821,
- no_content_204_otp_6982,
- missing_CR_otp_7304,
- {group, otp_7883},
- {group, otp_8154},
- {group, otp_8106},
- otp_8056,
- otp_8352,
- otp_8371,
- otp_8739]},
- {otp_7883, [], [otp_7883_1,
- otp_7883_2]},
- {otp_8154, [], [otp_8154_1]},
- {otp_8106, [], [otp_8106_pid,
- otp_8106_fun,
- otp_8106_mfa]},
- {ipv6, [], [ipv6_ipcomm, ipv6_essl]}
+ {http, [], real_requests()},
+ {sim_http, [], only_simulated()},
+ {https, [], real_requests()},
+ {sim_https, [], only_simulated()},
+ {misc, [], misc()}
].
+real_requests()->
+ [
+ head,
+ get,
+ post,
+ post_stream,
+ async,
+ pipeline,
+ persistent_connection,
+ save_to_file,
+ save_to_file_async,
+ headers_as_is,
+ page_does_not_exist,
+ emulate_lower_versions,
+ headers,
+ headers_as_is,
+ empty_body,
+ stream,
+ stream_to_pid,
+ stream_through_fun,
+ stream_through_mfa,
+ streaming_error,
+ inet_opts,
+ invalid_headers
+ ].
-init_per_group(ipv6 = _GroupName, Config) ->
- case inets_test_lib:has_ipv6_support() of
- {ok, _} ->
- Config;
- _ ->
- {skip, "Host does not support IPv6"}
- end;
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
+only_simulated() ->
+ [
+ cookie,
+ cookie_profile,
+ trace,
+ stream_once,
+ no_content_204,
+ tolerate_missing_CR,
+ userinfo,
+ bad_response,
+ internal_server_error,
+ invalid_http,
+ headers_dummy,
+ empty_response_header,
+ remote_socket_close,
+ remote_socket_close_async,
+ transfer_encoding,
+ redirect_loop,
+ redirect_moved_permanently,
+ redirect_multiple_choises,
+ redirect_found,
+ redirect_see_other,
+ redirect_temporary_redirect,
+ port_in_host_header,
+ relaxed
+ ].
+misc() ->
+ [
+ server_does_not_exist,
+ timeout_memory_leak,
+ wait_for_whole_response
+ ].
%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
-
- ?PRINT_SYSTEM_INFO([]),
+init_per_suite(Config) ->
PrivDir = ?config(priv_dir, Config),
DataDir = ?config(data_dir, Config),
+ inets_test_lib:start_apps([inets]),
ServerRoot = filename:join(PrivDir, "server_root"),
DocRoot = filename:join(ServerRoot, "htdocs"),
- IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
- SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
-
setup_server_dirs(ServerRoot, DocRoot, DataDir),
- create_config(IpConfFile, ip_comm, ?IP_PORT, PrivDir, ServerRoot,
- DocRoot, DataDir),
- create_config(SslConfFile, ssl, ?SSL_PORT, PrivDir, ServerRoot,
- DocRoot, DataDir),
+ [{server_root, ServerRoot}, {doc_root, DocRoot} | Config].
- Cgi = case test_server:os_type() of
- {win32, _} ->
- filename:join([ServerRoot, "cgi-bin", "cgi_echo.exe"]);
- _ ->
- filename:join([ServerRoot, "cgi-bin", "cgi_echo"])
- end,
-
- {ok, FileInfo} = file:read_file_info(Cgi),
- ok = file:write_file_info(Cgi, FileInfo#file_info{mode = 8#00755}),
-
- [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
- {server_root, ServerRoot},
- {doc_root, DocRoot},
- {local_port, ?IP_PORT},
- {local_ssl_port, ?SSL_PORT} | Config].
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
end_per_suite(Config) ->
- PrivDir = ?config(priv_dir, Config),
+ inets_test_lib:stop_apps([inets]),
+ PrivDir = ?config(priv_dir, Config),
inets_test_lib:del_dirs(PrivDir),
- application:stop(inets),
- application:stop(ssl),
ok.
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(Case, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
-
-init_per_testcase(otp_8154_1 = Case, Config) ->
- init_per_testcase(Case, 5, Config);
-
-init_per_testcase(initial_server_connect = Case, Config) ->
- %% Try to check if crypto actually exist or not,
- %% this test case does not work unless it does
- try
- begin
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- inets:start(),
- Config
- end
+init_per_group(misc = Group, Config) ->
+ start_apps(Group),
+ Inet = inet_version(),
+ ok = httpc:set_options([{ipfamily, Inet}]),
+ Config;
+
+init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https->
+ start_apps(Group),
+ StartSsl = try ssl:start()
catch
- throw:{error, {failed_starting, App, ActualError}} ->
- tsp("init_per_testcase(~w) -> failed starting ~w: "
- "~n ~p", [Case, App, ActualError]),
- SkipString =
- "Could not start " ++ atom_to_list(App),
- skip(SkipString);
- _:X ->
- SkipString =
- lists:flatten(
- io_lib:format("Failed starting apps: ~p", [X])),
- skip(SkipString)
+ Error:Reason ->
+ {skip, lists:flatten(io_lib:format("Failed to start apps for https Error=~p Reason=~p", [Error, Reason]))}
+ end,
+ case StartSsl of
+ {error, {already_started, _}} ->
+ do_init_per_group(Group, Config0);
+ ok ->
+ do_init_per_group(Group, Config0);
+ _ ->
+ StartSsl
end;
-init_per_testcase(Case, Config) ->
- init_per_testcase(Case, 2, Config).
-
-init_per_testcase(Case, Timeout, Config) ->
- io:format(user,
- "~n~n*** INIT ~w:~w[~w] ***"
- "~n~n", [?MODULE, Case, Timeout]),
+init_per_group(Group, Config0) ->
+ start_apps(Group),
+ Config = proplists:delete(port, Config0),
+ Port = server_start(Group, server_config(Group, Config)),
+ [{port, Port} | Config].
- PrivDir = ?config(priv_dir, Config),
- application:stop(inets),
- Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
- TmpConfig = lists:keydelete(watchdog, 1, Config),
- IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
- SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
-
- %% inets:enable_trace(max, io, httpd),
- %% inets:enable_trace(max, io, httpc),
- %% inets:enable_trace(max, io, all),
-
- NewConfig =
- case atom_to_list(Case) of
- [$s, $s, $l | _] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
- [{watchdog, Dog} | TmpConfig]);
-
- [$e, $s, $s, $l | _] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- init_per_testcase_ssl(essl, PrivDir, SslConfFile,
- [{watchdog, Dog} | TmpConfig]);
-
- "proxy_" ++ Rest ->
- io:format("init_per_testcase -> Rest: ~p~n", [Rest]),
- case Rest of
- "https_not_supported" ->
- tsp("init_per_testcase -> [proxy case] start inets"),
- inets:start(),
- tsp("init_per_testcase -> "
- "[proxy case] start crypto, public_key and ssl"),
- try ?ENSURE_STARTED([crypto, public_key, ssl]) of
- ok ->
- [{watchdog, Dog} | TmpConfig]
- catch
- throw:{error, {failed_starting, App, _}} ->
- SkipString =
- "Could not start " ++ atom_to_list(App),
- skip(SkipString);
- _:X ->
- SkipString =
- lists:flatten(
- io_lib:format("Failed starting apps: ~p", [X])),
- skip(SkipString)
- end;
-
- _ ->
- %% We use erlang.org for the proxy tests
- %% and after the switch to erlang-web, many
- %% of the test cases no longer work (erlang.org
- %% previously run on Apache).
- %% Until we have had time to update inets
- %% (and updated erlang.org to use that inets)
- %% and the test cases, we simply skip the
- %% problematic test cases.
- %% This is not ideal, but I am busy....
- case is_proxy_available(?PROXY, ?PROXY_PORT) of
- true ->
- BadCases =
- [
- "delete",
- "get",
- "head",
- "not_modified_otp_6821",
- "options",
- "page_does_not_exist",
- "post",
- "put",
- "stream"
- ],
- case lists:member(Rest, BadCases) of
- true ->
- [skip("TC and server not compatible") |
- TmpConfig];
- false ->
- inets:start(),
- [{watchdog, Dog} | TmpConfig]
- end;
- false ->
- [skip("proxy not responding") | TmpConfig]
- end
- end;
-
- "ipv6_" ++ _Rest ->
- %% Ensure needed apps (crypto, public_key and ssl) are started
- try ?ENSURE_STARTED([crypto, public_key, ssl]) of
- ok ->
- Profile = ipv6,
- %% A stand-alone profile is represented by a pid()
- {ok, ProfilePid} =
- inets:start(httpc,
- [{profile, Profile},
- {data_dir, PrivDir}], stand_alone),
- ok = httpc:set_options([{ipfamily, inet6}],
- ProfilePid),
- tsp("httpc profile pid: ~p", [ProfilePid]),
- [{watchdog, Dog}, {profile, ProfilePid}| TmpConfig]
- catch
- throw:{error, {failed_starting, App, ActualError}} ->
- tsp("init_per_testcase(~w) -> failed starting ~w: "
- "~n ~p", [Case, App, ActualError]),
- SkipString =
- "Could not start " ++ atom_to_list(App),
- skip(SkipString);
- _:X ->
- SkipString =
- lists:flatten(
- io_lib:format("Failed starting apps: ~p", [X])),
- skip(SkipString)
- end;
-
- _ ->
- %% Try inet6fb4 on windows...
- %% No need? Since it is set above?
-
- %% tsp("init_per_testcase -> allways try IPv6 on windows"),
- %% ?RUN_ON_WINDOWS(
- %% fun() ->
- %% tsp("init_per_testcase:set_options_fun -> "
- %% "set-option ipfamily to inet6fb4"),
- %% Res = httpc:set_options([{ipfamily, inet6fb4}]),
- %% tsp("init_per_testcase:set_options_fun -> "
- %% "~n Res: ~p", [Res]),
- %% Res
- %% end),
-
- TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
- %% Will start inets
- tsp("init_per_testcase -> try start server"),
- Server = start_http_server(PrivDir, IpConfFile),
- [{watchdog, Dog}, {local_server, Server} | TmpConfig2]
- end,
-
- %% <IPv6>
- %% Set default ipfamily to the same as the main server has by default
- %% This makes the client try w/ ipv6 before falling back to ipv4,
- %% as that is what the server is configured to do.
- %% Note that this is required for the tests to run on *BSD w/ ipv6 enabled
- %% as well as on Windows. The Linux behaviour of allowing ipv4 connects
- %% to ipv6 sockets is not required or even encouraged.
-
- tsp("init_per_testcase -> Options before ipfamily set: ~n~p",
- [httpc:get_options(all)]),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- tsp("init_per_testcase -> Options after ipfamily set: ~n~p",
- [httpc:get_options(all)]),
-
- %% Note that the IPv6 test case(s) *must* use inet6,
- %% so this value will be overwritten (see "ipv6_" below).
- %% </IPv6>
-
- %% This will fail for the ipv6_ - cases (but that is ok)
- ProxyExceptions = ["localhost", ?IPV6_LOCAL_HOST],
- tsp("init_per_testcase -> Options before proxy set: ~n~p",
- [httpc:get_options(all)]),
- ok = httpc:set_options([{proxy, {{?PROXY, ?PROXY_PORT}, ProxyExceptions}}]),
- tsp("init_per_testcase -> Options after proxy set: ~n~p",
- [httpc:get_options(all)]),
- inets:enable_trace(max, io, httpc),
- %% inets:enable_trace(max, io, all),
- %% snmp:set_trace([gen_tcp]),
- tsp("init_per_testcase(~w) -> done when"
- "~n NewConfig: ~p"
- "~n~n", [Case, NewConfig]),
- NewConfig.
-
-
-init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
- tsp("init_per_testcase_ssl(~w) -> stop ssl", [Tag]),
- application:stop(ssl),
- Config2 = lists:keydelete(local_ssl_server, 1, Config),
- %% Will start inets
- tsp("init_per_testcase_ssl(~w) -> try start http server (including inets)",
- [Tag]),
- Server = inets_test_lib:start_http_server(
- filename:join(PrivDir, SslConfFile), Tag),
- tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
- [{local_ssl_server, Server} | Config2].
-
-start_http_server(ConfDir, ConfFile) ->
- inets_test_lib:start_http_server( filename:join(ConfDir, ConfFile) ).
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(Case, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
+end_per_group(_, _Config) ->
+ ok.
+do_init_per_group(Group, Config0) ->
+ Config = proplists:delete(port, Config0),
+ Port = server_start(Group, server_config(Group, Config)),
+ [{port, Port} | Config].
%%--------------------------------------------------------------------
-end_per_testcase(http_save_to_file = Case, Config) ->
- io:format(user, "~n~n*** END ~w:~w ***~n~n",
- [?MODULE, Case]),
- PrivDir = ?config(priv_dir, Config),
- FullPath = filename:join(PrivDir, "dummy.html"),
- file:delete(FullPath),
- finish(Config);
-
-end_per_testcase(Case, Config) ->
- io:format(user, "~n~n*** END ~w:~w ***~n~n",
- [?MODULE, Case]),
- dbg:stop(), % ?
- case atom_to_list(Case) of
- "ipv6_" ++ _Rest ->
- tsp("end_per_testcase(~w) -> stop ssl", [Case]),
- application:stop(ssl),
- tsp("end_per_testcase(~w) -> stop public_key", [Case]),
- application:stop(public_key),
- tsp("end_per_testcase(~w) -> stop crypto", [Case]),
- application:stop(crypto),
- ProfilePid = ?config(profile, Config),
- tsp("end_per_testcase(~w) -> stop httpc profile (~p)",
- [Case, ProfilePid]),
- unlink(ProfilePid),
- inets:stop(stand_alone, ProfilePid),
- tsp("end_per_testcase(~w) -> httpc profile (~p) stopped",
- [Case, ProfilePid]),
- ok;
- _ ->
- ok
- end,
- finish(Config).
-
-finish(Config) ->
- Dog = ?config(watchdog, Config),
- case Dog of
- undefined ->
- ok;
- _ ->
- tsp("finish -> stop watchdog (~p)", [Dog]),
- test_server:timetrap_cancel(Dog)
- end.
+init_per_testcase(pipeline, Config) ->
+ inets:start(httpc, [{profile, pipeline}]),
+ httpc:set_options([{pipeline_timeout, 50000},
+ {max_pipeline_length, 3}], pipeline),
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
+ Config;
+init_per_testcase(persistent_connection, Config) ->
+ inets:start(httpc, [{profile, persistent}]),
+ httpc:set_options([{keep_alive_timeout, 50000},
+ {max_keep_alive_length, 3}], persistent_connection),
+ Config;
+init_per_testcase(_Case, Config) ->
+ Config.
-%%-------------------------------------------------------------------------
+end_per_testcase(pipeline, _Config) ->
+ inets:stop(httpc, pipeline);
+end_per_testcase(persistent_connection, _Config) ->
+ inets:stop(httpc, persistent);
-http_options(doc) ->
- ["Test http options request against local server."];
-http_options(suite) ->
- [];
-http_options(Config) when is_list(Config) ->
- skip("Not supported by httpd").
-
-http_head(doc) ->
- ["Test http head request against local server."];
-http_head(suite) ->
- [];
-http_head(Config) when is_list(Config) ->
- tsp("http_head -> entry with"
- "~n Config: ~p", [Config]),
- Method = head,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- HttpOpts = [],
- Opts = [],
- VerifyResult =
- fun({ok, {{_,200,_}, [_ | _], []}}) ->
- ok;
- ({ok, UnexpectedReply}) ->
- tsp("http_head:verify_fun -> Unexpected Reply: "
- "~n ~p", [UnexpectedReply]),
- tsf({unexpected_reply, UnexpectedReply});
- ({error, Reason} = Error) ->
- tsp("http_head:verify_fun -> Error reply: "
- "~n Reason: ~p", [Reason]),
- tsf({bad_reply, Error})
- end,
- simple_request_and_verify(Config,
- Method, Request, HttpOpts, Opts, VerifyResult).
+end_per_testcase(_Case, _Config) ->
+ ok.
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
-%%-------------------------------------------------------------------------
+head() ->
+ [{doc, "Test http head request against local server."}].
-http_get(doc) ->
- ["Test http get request against local server"];
-http_get(suite) ->
- [];
-http_get(Config) when is_list(Config) ->
- tsp("http_get -> entry with"
- "~n Config: ~p", [Config]),
- case ?config(local_server, Config) of
- ok ->
- tsp("local-server running"),
- Method = get,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- Timeout = timer:seconds(1),
- ConnTimeout = Timeout + timer:seconds(1),
- HttpOptions1 = [{timeout, Timeout},
- {connect_timeout, ConnTimeout}],
- Options1 = [],
- Body =
- case httpc:request(Method, Request, HttpOptions1, Options1) of
- {ok, {{_,200,_}, [_ | _], ReplyBody = [_ | _]}} ->
- ReplyBody;
- {ok, UnexpectedReply1} ->
- tsf({unexpected_reply, UnexpectedReply1});
- {error, _} = Error1 ->
- tsf({bad_reply, Error1})
- end,
-
- %% eqvivivalent to httpc:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(Body),
-
- HttpOptions2 = [],
- Options2 = [{body_format, binary}],
- case httpc:request(Method, Request, HttpOptions2, Options2) of
- {ok, {{_,200,_}, [_ | _], Bin}} when is_binary(Bin) ->
- ok;
- {ok, {{_,200,_}, [_ | _], BadBin}} ->
- tsf({body_format_not_binary, BadBin});
- {ok, UnexpectedReply2} ->
- tsf({unexpected_reply, UnexpectedReply2});
- {error, _} = Error2 ->
- tsf({bad_reply, Error2})
- end;
- _ ->
- skip("Failed to start local http-server")
- end.
+head(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {ok, {{_,200,_}, [_ | _], []}} = httpc:request(head, Request, [], []).
+%%--------------------------------------------------------------------
+get() ->
+ [{doc, "Test http get request against local server"}].
+get(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {ok, {{_,200,_}, [_ | _], Body = [_ | _]}} = httpc:request(get, Request, [], []),
-%%-------------------------------------------------------------------------
+ inets_test_lib:check_body(Body),
-http_post(doc) ->
- ["Test http post request against local server. We do in this case "
+ {ok, {{_,200,_}, [_ | _], BinBody}} = httpc:request(get, Request, [], [{body_format, binary}]),
+ true = is_binary(BinBody).
+%%--------------------------------------------------------------------
+post() ->
+ [{"Test http post request against local server. We do in this case "
"only care about the client side of the the post. The server "
- "script will not actually use the post data."];
-http_post(suite) ->
- [];
-http_post(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
-
- URL = case test_server:os_type() of
- {win32, _} ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo.exe";
- _ ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo"
-
- end,
- %% Cgi-script expects the body length to be 100
- Body = lists:duplicate(100, "1"),
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(post, {URL, [{"expect","100-continue"}],
- "text/plain", Body}, [], []),
-
- {ok, {{_,504,_}, [_ | _], []}} =
- httpc:request(post, {URL, [{"expect","100-continue"}],
- "text/plain", "foobar"}, [], []);
- _ ->
- skip("Failed to start local http-server")
- end.
-
-%%-------------------------------------------------------------------------
-http_post_streaming(doc) ->
- ["Test streaming http post request against local server. "
- "We only care about the client side of the the post. "
- "The server script will not actually use the post data."];
-http_post_streaming(suite) ->
- [];
-http_post_streaming(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = case test_server:os_type() of
- {win32, _} ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo.exe";
- _ ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo"
- end,
- %% Cgi-script expects the body length to be 100
- BodyFun = fun(0) ->
- io:format("~w:http_post_streaming_fun -> "
- "zero~n", [?MODULE]),
- eof;
- (LenLeft) ->
- io:format("~w:http_post_streaming_fun -> "
- "LenLeft: ~p~n", [?MODULE, LenLeft]),
- {ok, lists:duplicate(10, "1"), LenLeft - 10}
- end,
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(post, {URL,
- [{"expect", "100-continue"},
- {"content-length", "100"}],
- "text/plain", {BodyFun, 100}}, [], []),
-
- {ok, {{_,504,_}, [_ | _], []}} =
- httpc:request(post, {URL,
- [{"expect", "100-continue"},
- {"content-length", "10"}],
- "text/plain", {BodyFun, 10}}, [], []);
-
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-http_emulate_lower_versions(doc) ->
- ["Perform request as 0.9 and 1.0 clients."];
-http_emulate_lower_versions(suite) ->
- [];
-http_emulate_lower_versions(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, Body0} =
- httpc:request(get, {URL, []}, [{version, "HTTP/0.9"}], []),
- inets_test_lib:check_body(Body0),
- {ok, {{"HTTP/1.0", 200, _}, [_ | _], Body1 = [_ | _]}} =
- httpc:request(get, {URL, []}, [{version, "HTTP/1.0"}], []),
- inets_test_lib:check_body(Body1),
- {ok, {{"HTTP/1.1", 200, _}, [_ | _], Body2 = [_ | _]}} =
- httpc:request(get, {URL, []}, [{version, "HTTP/1.1"}], []),
- inets_test_lib:check_body(Body2);
- _->
- skip("Failed to start local http-server")
- end.
+ "script will not actually use the post data."}].
+post(Config) when is_list(Config) ->
+ CGI = case test_server:os_type() of
+ {win32, _} ->
+ "/cgi-bin/cgi_echo.exe";
+ _ ->
+ "/cgi-bin/cgi_echo"
+ end,
+ URL = url(group_name(Config), CGI, Config),
-%%-------------------------------------------------------------------------
+ %% Cgi-script expects the body length to be 100
+ Body = lists:duplicate(100, "1"),
-http_relaxed(doc) ->
- ["Test relaxed mode"];
-http_relaxed(suite) ->
- [];
-http_relaxed(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
- %% ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++
- "/missing_reason_phrase.html",
-
- {error, Reason} =
- httpc:request(get, {URL, []}, [{relaxed, false}], []),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(post, {URL, [{"expect","100-continue"}],
+ "text/plain", Body}, [], []),
- test_server:format("Not relaxed: ~p~n", [Reason]),
-
- {ok, {{_, 200, _}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, []}, [{relaxed, true}], []),
+ {ok, {{_,504,_}, [_ | _], []}} =
+ httpc:request(post, {URL, [{"expect","100-continue"}],
+ "text/plain", "foobar"}, [], []).
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipv6, enabled}]),
- %% ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+%%--------------------------------------------------------------------
+post_stream() ->
+ [{"Test streaming http post request against local server. "
+ "We only care about the client side of the the post. "
+ "The server script will not actually use the post data."}].
+post_stream(Config) when is_list(Config) ->
+ CGI = case test_server:os_type() of
+ {win32, _} ->
+ "/cgi-bin/cgi_echo.exe";
+ _ ->
+ "/cgi-bin/cgi_echo"
+ end,
+ URL = url(group_name(Config), CGI, Config),
-%%-------------------------------------------------------------------------
-http_dummy_pipe(doc) ->
- ["Test pipelining code."];
-http_dummy_pipe(suite) ->
- [];
-http_dummy_pipe(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/foobar.html",
+ %% Cgi-script expects the body length to be 100
+ BodyFun = fun(0) ->
+ eof;
+ (LenLeft) ->
+ {ok, lists:duplicate(10, "1"), LenLeft - 10}
+ end,
- test_pipeline(URL),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(post, {URL,
+ [{"expect", "100-continue"},
+ {"content-length", "100"}],
+ "text/plain", {BodyFun, 100}}, [], []),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ {ok, {{_,504,_}, [_ | _], []}} =
+ httpc:request(post, {URL,
+ [{"expect", "100-continue"},
+ {"content-length", "10"}],
+ "text/plain", {BodyFun, 10}}, [], []).
-http_inets_pipe(doc) ->
- ["Test pipelining code."];
-http_inets_pipe(suite) ->
- [];
-http_inets_pipe(Config) when is_list(Config) ->
-
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- test_pipeline(URL);
- _ ->
- skip("Failed to start local http-server")
+%%--------------------------------------------------------------------
+trace() ->
+ [{doc, "Perform a TRACE request."}].
+trace(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/trace.html", Config), []},
+ case httpc:request(trace, Request, [], []) of
+ {ok, {{_,200,_}, [_ | _], "TRACE /trace.html" ++ _}} ->
+ ok;
+ Other ->
+ ct:fail({unexpected, Other})
end.
+%%--------------------------------------------------------------------
-test_pipeline(URL) ->
- p("test_pipeline -> entry with"
- "~n URL: ~p", [URL]),
-
- httpc:set_options([{pipeline_timeout, 50000}]),
-
- p("test_pipeline -> issue (async) request 1"
- "~n when profile info: ~p", [httpc:info()]),
- {ok, RequestIdA1} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestIdA1: ~p", [RequestIdA1]),
- p("test_pipeline -> RequestIdA1: ~p"
- "~n when profile info: ~p", [RequestIdA1, httpc:info()]),
-
- %% Make sure pipeline is initiated
- p("test_pipeline -> sleep some", []),
- test_server:sleep(4000),
-
- p("test_pipeline -> issue (async) request A2, A3 and A4"
- "~n when profile info: ~p", [httpc:info()]),
- {ok, RequestIdA2} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdA3} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdA4} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p",
- [RequestIdA2, RequestIdA3, RequestIdA4]),
- p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p"
- "~n when profile info: ~p",
- [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]),
-
- p("test_pipeline -> issue (sync) request 3"),
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, []}, [], []),
-
- p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4"
- "~n when profile info: ~p", [httpc:info()]),
- pipeline_await_async_reply([{RequestIdA1, a1, 200},
- {RequestIdA2, a2, 200},
- {RequestIdA3, a3, 200},
- {RequestIdA4, a4, 200}], ?MINS(1)),
-
- p("test_pipeline -> sleep some"
- "~n when profile info: ~p", [httpc:info()]),
- test_server:sleep(4000),
-
- p("test_pipeline -> issue (async) request B1, B2, B3 and B4"
- "~n when profile info: ~p", [httpc:info()]),
- {ok, RequestIdB1} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdB2} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdB3} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdB4} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p",
- [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]),
- p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p"
- "~n when profile info: ~p",
- [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]),
-
- p("test_pipeline -> cancel (async) request B2"
- "~n when profile info: ~p", [httpc:info()]),
- ok = httpc:cancel_request(RequestIdB2),
-
- p("test_pipeline -> "
- "expect *no* reply for cancelled (async) request B2 (for 3 secs)"
- "~n when profile info: ~p", [httpc:info()]),
- receive
- {http, {RequestIdB2, _}} ->
- tsf(http_cancel_request_failed)
- after 3000 ->
- ok
- end,
-
- p("test_pipeline -> expect reply for (async) request B1, B3 and B4"
- "~n when profile info: ~p", [httpc:info()]),
- Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200},
- {RequestIdB3, b3, 200},
- {RequestIdB4, b4, 200}], ?MINS(1)),
- [{b1, Body}|_] = Bodies,
-
- p("test_pipeline -> check reply for (async) request B1"
- "~n when profile info: ~p", [httpc:info()]),
- inets_test_lib:check_body(binary_to_list(Body)),
-
- p("test_pipeline -> ensure no unexpected incomming"
- "~n when profile info: ~p", [httpc:info()]),
- receive
- {http, Any} ->
- tsf({unexpected_message, Any})
- after 500 ->
- ok
- end,
-
- p("test_pipeline -> done"
- "~n when profile info: ~p", [httpc:info()]),
- ok.
-
-pipeline_await_async_reply(ReqIds, Timeout) ->
- pipeline_await_async_reply(ReqIds, Timeout, []).
+pipeline(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {ok, _} = httpc:request(get, Request, [], [], pipeline),
+ keep_alive_requests(Request, pipeline).
-pipeline_await_async_reply([], _, Acc) ->
- lists:keysort(1, Acc);
-pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 ->
- T1 = inets_test_lib:timestamp(),
- p("pipeline_await_async_reply -> await replies"
- "~n ReqIds: ~p"
- "~n Timeout: ~p", [ReqIds, Timeout]),
- receive
- {http, {RequestId, {{_, Status, _}, _, Body}}} ->
- p("pipeline_await_async_reply -> received reply for"
- "~n RequestId: ~p"
- "~n Status: ~p", [RequestId, Status]),
- case lists:keysearch(RequestId, 1, ReqIds) of
- {value, {RequestId, N, Status}} ->
- p("pipeline_await_async_reply -> "
- "found expected request ~w", [N]),
- ReqIds2 = lists:keydelete(RequestId, 1, ReqIds),
- NewTimeout = Timeout - (inets_test_lib:timestamp()-T1),
- pipeline_await_async_reply(ReqIds2, NewTimeout,
- [{N, Body} | Acc]);
- {value, {RequestId, N, WrongStatus}} ->
- p("pipeline_await_async_reply -> "
- "found request ~w with wrong status", [N]),
- tsf({reply_with_unexpected_status,
- {RequestId, N, WrongStatus}});
- false ->
- tsf({unexpected_reply, {RequestId, Status}})
- end;
- {http, Msg} ->
- tsf({unexpected_reply, Msg})
- after Timeout ->
- receive
- Any ->
- tsp("pipeline_await_async_reply -> "
- "received unknown data after timeout: "
- "~n ~p", [Any]),
- tsf({timeout, {unknown, Any}})
- end
- end;
-pipeline_await_async_reply(ReqIds, _, Acc) ->
- tsp("pipeline_await_async_reply -> "
- "timeout: "
- "~n ~p"
- "~nwhen"
- "~n ~p", [ReqIds, Acc]),
- tsf({timeout, ReqIds, Acc}).
-
+%%--------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-http_trace(doc) ->
- ["Perform a TRACE request that goes through a proxy."];
-http_trace(suite) ->
- [];
-http_trace(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- case httpc:request(trace, {URL, []}, [], []) of
- {ok, {{_,200,_}, [_ | _], "TRACE /dummy.html" ++ _}} ->
- ok;
- {ok, {{_,200,_}, [_ | _], WrongBody}} ->
- tsf({wrong_body, WrongBody});
- {ok, WrongReply} ->
- tsf({wrong_reply, WrongReply});
- Error ->
- tsf({failed, Error})
- end;
- _ ->
- skip("Failed to start local http-server")
- end.
-%%-------------------------------------------------------------------------
-http_async(doc) ->
- ["Test an asynchrony http request."];
-http_async(suite) ->
- [];
-http_async(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, RequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
-
- Body =
- receive
- {http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
- BinBody;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- inets_test_lib:check_body(binary_to_list(Body)),
-
- {ok, NewRequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- ok = httpc:cancel_request(NewRequestId),
- receive
- {http, {NewRequestId, _NewResult}} ->
- tsf(http_cancel_request_failed)
- after 3000 ->
- ok
- end;
- _ ->
- skip("Failed to start local http-server")
- end.
+persistent_connection(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {ok, _} = httpc:request(get, Request, [], [], persistent),
+ keep_alive_requests(Request, persistent).
%%-------------------------------------------------------------------------
-http_save_to_file(doc) ->
- ["Test to save the http body to a file"];
-http_save_to_file(suite) ->
- [];
-http_save_to_file(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- PrivDir = ?config(priv_dir, Config),
- FilePath = filename:join(PrivDir, "dummy.html"),
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, saved_to_file}
- = httpc:request(get, {URL, []}, [], [{stream, FilePath}]),
- {ok, Bin} = file:read_file(FilePath),
- {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
- Bin == Body;
- _ ->
- skip("Failed to start local http-server")
- end.
+async() ->
+ [{doc, "Test an asynchrony http request."}].
+async(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {ok, RequestId} =
+ httpc:request(get, Request, [], [{sync, false}]),
+ Body =
+ receive
+ {http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
+ BinBody;
+ {http, Msg} ->
+ ct:fail(Msg)
+ end,
+ inets_test_lib:check_body(binary_to_list(Body)),
-%%-------------------------------------------------------------------------
-http_save_to_file_async(doc) ->
- ["Test to save the http body to a file"];
-http_save_to_file_async(suite) ->
- [];
-http_save_to_file_async(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- PrivDir = ?config(priv_dir, Config),
- FilePath = filename:join(PrivDir, "dummy.html"),
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, RequestId} = httpc:request(get, {URL, []}, [],
- [{stream, FilePath},
- {sync, false}]),
- receive
- {http, {RequestId, saved_to_file}} ->
- ok;
- {http, Msg} ->
- tsf(Msg)
- end,
+ {ok, NewRequestId} =
+ httpc:request(get, Request, [], [{sync, false}]),
+ ok = httpc:cancel_request(NewRequestId).
- {ok, Bin} = file:read_file(FilePath),
- {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
- Bin == Body;
- _ ->
- skip("Failed to start local http-server")
- end.
%%-------------------------------------------------------------------------
-http_headers(doc) ->
- ["Use as many request headers as possible not used in proxy_headers"];
-http_headers(suite) ->
- [];
-http_headers(Config) when is_list(Config) ->
-
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- DocRoot = ?config(doc_root, Config),
- {ok, FileInfo} =
- file:read_file_info(filename:join([DocRoot,"dummy.html"])),
- CreatedSec =
- calendar:datetime_to_gregorian_seconds(
- FileInfo#file_info.mtime),
-
- Mod = httpd_util:rfc1123_date(
- calendar:gregorian_seconds_to_datetime(
- CreatedSec-1)),
-
- Date = httpd_util:rfc1123_date({date(), time()}),
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, [{"If-Modified-Since",
- Mod},
- {"From","[email protected]"},
- {"Date", Date}
- ]}, [], []),
-
- Mod1 = httpd_util:rfc1123_date(
- calendar:gregorian_seconds_to_datetime(
- CreatedSec+1)),
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, [{"If-UnModified-Since",
- Mod1}
- ]}, [], []),
-
- Tag = httpd_util:create_etag(FileInfo),
-
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, [{"If-Match",
- Tag}
- ]}, [], []),
-
- {ok, {{_,200,_}, [_ | _], _}} =
- httpc:request(get, {URL, [{"If-None-Match",
- "NotEtag,NeihterEtag"},
- {"Connection", "Close"}
- ]}, [], []),
+save_to_file() ->
+ [{doc, "Test to save the http body to a file"}].
+save_to_file(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FilePath = filename:join(PrivDir, "dummy.html"),
+ URL = url(group_name(Config), "/dummy.html", Config),
+ Request = {URL, []},
+ {ok, saved_to_file}
+ = httpc:request(get, Request, [], [{stream, FilePath}]),
+ {ok, Bin} = file:read_file(FilePath),
+ {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
+ Bin == Body.
+
+%%-------------------------------------------------------------------------
+save_to_file_async() ->
+ [{doc,"Test to save the http body to a file"}].
+save_to_file_async(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ FilePath = filename:join(PrivDir, "dummy.html"),
+ URL = url(group_name(Config), "/dummy.html", Config),
+ Request = {URL, []},
+ {ok, RequestId} = httpc:request(get, Request, [],
+ [{stream, FilePath},
+ {sync, false}]),
+ receive
+ {http, {RequestId, saved_to_file}} ->
ok;
- _ ->
- skip("Failed to start local http-server")
- end.
+ {http, Msg} ->
+ ct:fail(Msg)
+ end,
+ {ok, Bin} = file:read_file(FilePath),
+ {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
+ Bin == Body.
%%-------------------------------------------------------------------------
-http_headers_dummy(doc) ->
- ["Test the code for handling headers we do not want/can send "
- "to a real server. Note it is not logical to send"
- "all of these headers together, we only want to test that"
- "the code for handling headers will not crash."];
-http_headers_dummy(suite) ->
- [];
-http_headers_dummy(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy_headers.html",
-
- Foo = http_chunk:encode("foobar") ++
- binary_to_list(http_chunk:encode_last()),
- FooBar = Foo ++ "\r\n\r\nOther:inets_test\r\n\r\n",
-
- UserPasswd = base64:encode_to_string("Alladin:Sesame"),
- Auth = "Basic " ++ UserPasswd,
-
- %% The dummy server will ignore the headers, we only want to test
- %% that the client header-handling code. This would not
- %% be a vaild http-request!
- {ok, {{_,200,_}, [_ | _], [_|_]}} =
- httpc:request(post,
- {URL,
- [{"Via",
- "1.0 fred, 1.1 nowhere.com (Apache/1.1)"},
- {"Warning","1#pseudonym foobar"},
- {"Vary","*"},
- {"Upgrade","HTTP/2.0"},
- {"Pragma", "1#no-cache"},
- {"Cache-Control", "no-cache"},
- {"Connection", "close"},
- {"Date", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"Accept", " text/plain; q=0.5, text/html"},
- {"Accept-Language", "en"},
- {"Accept-Encoding","chunked"},
- {"Accept-Charset", "ISO8859-1"},
- {"Authorization", Auth},
- {"Expect", "1#100-continue"},
- {"User-Agent","inets"},
- {"Transfer-Encoding","chunked"},
- {"Range", " bytes=0-499"},
- {"If-Range", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"If-Match", "*"},
- {"Content-Type", "text/plain"},
- {"Content-Encoding", "chunked"},
- {"Content-Length", "6"},
- {"Content-Language", "en"},
- {"Content-Location", "http://www.foobar.se"},
- {"Content-MD5",
- "104528739076276072743283077410617235478"},
- {"Content-Range", "bytes 0-499/1234"},
- {"Allow", "GET"},
- {"Proxy-Authorization", Auth},
- {"Expires", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"Upgrade", "HTTP/2.0"},
- {"Last-Modified", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"Trailer","1#User-Agent"}
- ], "text/plain", FooBar},
- [], []),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
+stream() ->
+ [{doc, "Test the option stream for asynchrony requests"}].
+stream(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ stream_test(Request, {stream, self}).
%%-------------------------------------------------------------------------
-http_bad_response(doc) ->
- ["Test what happens when the server does not follow the protocol"];
-http_bad_response(suite) ->
- [];
-http_bad_response(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_crlf.html",
-
- URL1 = ?URL_START ++ integer_to_list(Port) ++ "/wrong_statusline.html",
-
- {error, timeout} = httpc:request(get, {URL, []}, [{timeout, 400}], []),
-
- {error, Reason} = httpc:request(URL1),
-
- test_server:format("Wrong Statusline: ~p~n", [Reason]),
+stream_once() ->
+ [{doc, "Test the option stream for asynchrony requests"}].
+stream_once(Config) when is_list(Config) ->
+ Request0 = {url(group_name(Config), "/dummy.html", Config), []},
+ stream_test(Request0, {stream, {self, once}}),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ Request1 = {url(group_name(Config), "/once.html", Config), []},
+ stream_test(Request1, {stream, {self, once}}),
+ Request2 = {url(group_name(Config), "/once_chunked.html", Config), []},
+ stream_test(Request2, {stream, {self, once}}).
%%-------------------------------------------------------------------------
-ssl_head(doc) ->
- ["Same as http_head/1 but over ssl sockets."];
-ssl_head(suite) ->
- [];
-ssl_head(Config) when is_list(Config) ->
- ssl_head(ssl, Config).
+redirect_multiple_choises() ->
+ [{doc, "The user agent, selection of the most appropriate choice MAY "
+ "be performed automatically."}].
+redirect_multiple_choises(Config) when is_list(Config) ->
+ URL300 = url(group_name(Config), "/300.html", Config),
-essl_head(doc) ->
- ["Same as http_head/1 but over ssl sockets."];
-essl_head(suite) ->
- [];
-essl_head(Config) when is_list(Config) ->
- ssl_head(essl, Config).
-
-ssl_head(SslTag, Config) ->
- tsp("ssl_head -> entry with"
- "~n SslTag: ~p"
- "~n Config: ~p", [SslTag, Config]),
- case ?config(local_ssl_server, Config) of
- ok ->
- DataDir = ?config(data_dir, Config),
- Port = ?config(local_ssl_port, Config),
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig =
- case SslTag of
- ssl ->
- SSLOptions;
- essl ->
- {essl, SSLOptions}
- end,
- tsp("ssl_head -> make request using: "
- "~n URL: ~p"
- "~n SslTag: ~p"
- "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- {ok, {{_,200, _}, [_ | _], []}} =
- httpc:request(head, {URL, []}, [{ssl, SSLConfig}], []);
- {ok, _} ->
- skip("local http-server not started");
- _ ->
- skip("SSL not started")
- end.
+ catch {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL300, []}, [], []),
-
+ {ok, {{_,300,_}, [_ | _], _}} =
+ httpc:request(get, {URL300, []}, [{autoredirect, false}], []).
%%-------------------------------------------------------------------------
-ssl_get(doc) ->
- ["Same as http_get/1 but over ssl sockets."];
-ssl_get(suite) ->
- [];
-ssl_get(Config) when is_list(Config) ->
- ssl_get(ssl, Config).
+redirect_moved_permanently() ->
+ [{doc, "If the 301 status code is received in response to a request other "
+ "than GET or HEAD, the user agent MUST NOT automatically redirect the request "
+ "unless it can be confirmed by the user, since this might change "
+ "the conditions under which the request was issued."}].
+redirect_moved_permanently(Config) when is_list(Config) ->
-essl_get(doc) ->
- ["Same as http_get/1 but over ssl sockets."];
-essl_get(suite) ->
- [];
-essl_get(Config) when is_list(Config) ->
- ssl_get(essl, Config).
+ URL301 = url(group_name(Config), "/301.html", Config),
-ssl_get(SslTag, Config) when is_list(Config) ->
- case ?config(local_ssl_server, Config) of
- ok ->
- DataDir = ?config(data_dir, Config),
- Port = ?config(local_ssl_port, Config),
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig =
- case SslTag of
- ssl ->
- SSLOptions;
- essl ->
- {essl, SSLOptions}
- end,
- tsp("ssl_get -> make request using: "
- "~n URL: ~p"
- "~n SslTag: ~p"
- "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- case httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []) of
- {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} ->
- inets_test_lib:check_body(Body),
- ok;
- {ok, {StatusLine, Headers, _Body}} ->
- tsp("ssl_get -> unexpected result: "
- "~n StatusLine: ~p"
- "~n Headers: ~p", [StatusLine, Headers]),
- tsf({unexpected_response, StatusLine, Headers});
- {error, Reason} ->
- tsp("ssl_get -> request failed: "
- "~n Reason: ~p", [Reason]),
- tsf({request_failed, Reason})
- end;
- {ok, _} ->
- skip("local http-server not started");
- _ ->
- skip("SSL not started")
- end.
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, []}, [], []),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, []}, [], []),
+ {ok, {{_,301,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, [],"text/plain", "foobar"},
+ [], []).
%%-------------------------------------------------------------------------
-ssl_trace(doc) ->
- ["Same as http_trace/1 but over ssl sockets."];
-ssl_trace(suite) ->
- [];
-ssl_trace(Config) when is_list(Config) ->
- ssl_trace(ssl, Config).
+redirect_found() ->
+ [{doc," If the 302 status code is received in response to a request other "
+ "than GET or HEAD, the user agent MUST NOT automatically redirect the "
+ "request unless it can be confirmed by the user, since this might change "
+ "the conditions under which the request was issued."}].
+redirect_found(Config) when is_list(Config) ->
-essl_trace(doc) ->
- ["Same as http_trace/1 but over ssl sockets."];
-essl_trace(suite) ->
- [];
-essl_trace(Config) when is_list(Config) ->
- ssl_trace(essl, Config).
+ URL302 = url(group_name(Config), "/302.html", Config),
-ssl_trace(SslTag, Config) when is_list(Config) ->
- case ?config(local_ssl_server, Config) of
- ok ->
- DataDir = ?config(data_dir, Config),
- Port = ?config(local_ssl_port, Config),
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig =
- case SslTag of
- ssl ->
- SSLOptions;
- essl ->
- {essl, SSLOptions}
- end,
- tsp("ssl_trace -> make request using: "
- "~n URL: ~p"
- "~n SslTag: ~p"
- "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- case httpc:request(trace, {URL, []}, [{ssl, SSLConfig}], []) of
- {ok, {{_,200, _}, [_ | _], "TRACE /dummy.html" ++ _}} ->
- ok;
- {ok, {{_,200,_}, [_ | _], WrongBody}} ->
- tsf({wrong_body, WrongBody});
- {ok, WrongReply} ->
- tsf({wrong_reply, WrongReply});
- Error ->
- tsf({failed, Error})
- end;
- {ok, _} ->
- skip("local http-server not started");
- _ ->
- skip("SSL not started")
- end.
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL302, []}, [], []),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL302, []}, [], []),
+ {ok, {{_,302,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL302, [],"text/plain", "foobar"},
+ [], []).
%%-------------------------------------------------------------------------
-http_redirect(doc) ->
- ["Test redirect with dummy server as httpd does not implement"
- " server redirect"];
-http_redirect(suite) ->
- [];
-http_redirect(Config) when is_list(Config) ->
- tsp("http_redirect -> entry with"
- "~n Config: ~p", [Config]),
- case ?config(local_server, Config) of
- ok ->
- %% tsp("http_redirect -> set ipfamily option to inet"),
- %% ok = httpc:set_options([{ipfamily, inet}]),
+redirect_see_other() ->
+ [{doc, "The different URI SHOULD be given by the Location field in the response. "
+ "Unless the request method was HEAD, the entity of the response SHOULD contain a short "
+ "hypertext note with a hyperlink to the new URI(s). "}].
+redirect_see_other(Config) when is_list(Config) ->
- tsp("http_redirect -> start dummy server inet"),
- {DummyServerPid, Port} = dummy_server(ipv4),
- tsp("http_redirect -> server port = ~p", [Port]),
-
- URL300 = ?URL_START ++ integer_to_list(Port) ++ "/300.html",
-
- tsp("http_redirect -> issue request 1: "
- "~n ~p", [URL300]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL300, []}, [], []),
-
- tsp("http_redirect -> issue request 2: "
- "~n ~p", [URL300]),
- {ok, {{_,300,_}, [_ | _], _}} =
- httpc:request(get, {URL300, []}, [{autoredirect, false}], []),
-
- URL301 = ?URL_START ++ integer_to_list(Port) ++ "/301.html",
-
- tsp("http_redirect -> issue request 3: "
- "~n ~p", [URL301]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL301, []}, [], []),
-
- tsp("http_redirect -> issue request 4: "
- "~n ~p", [URL301]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL301, []}, [], []),
-
- tsp("http_redirect -> issue request 5: "
- "~n ~p", [URL301]),
- {ok, {{_,301,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL301, [],"text/plain", "foobar"},
- [], []),
-
- URL302 = ?URL_START ++ integer_to_list(Port) ++ "/302.html",
-
- tsp("http_redirect -> issue request 6: "
- "~n ~p", [URL302]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL302, []}, [], []),
- case httpc:request(get, {URL302, []}, [], []) of
- {ok, Reply7} ->
- case Reply7 of
- {{_,200,_}, [_ | _], [_|_]} ->
- tsp("http_redirect -> "
- "expected reply for request 7"),
- ok;
- {StatusLine, Headers, Body} ->
- tsp("http_redirect -> "
- "unexpected reply for request 7: "
- "~n StatusLine: ~p"
- "~n Headers: ~p"
- "~n Body: ~p",
- [StatusLine, Headers, Body]),
- tsf({unexpected_reply, Reply7})
- end;
- Error7 ->
- tsp("http_redirect -> "
- "unexpected result for request 7: "
- "~n Error7: ~p",
- [Error7]),
- tsf({unexpected_result, Error7})
- end,
-
- tsp("http_redirect -> issue request 7: "
- "~n ~p", [URL302]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL302, []}, [], []),
-
- tsp("http_redirect -> issue request 8: "
- "~n ~p", [URL302]),
- {ok, {{_,302,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL302, [],"text/plain", "foobar"},
- [], []),
-
- URL307 = ?URL_START ++ integer_to_list(Port) ++ "/307.html",
-
- tsp("http_redirect -> issue request 9: "
- "~n ~p", [URL307]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL307, []}, [], []),
-
- tsp("http_redirect -> issue request 10: "
- "~n ~p", [URL307]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL307, []}, [], []),
-
- tsp("http_redirect -> issue request 11: "
- "~n ~p", [URL307]),
- {ok, {{_,307,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL307, [],"text/plain", "foobar"},
- [], []),
-
- tsp("http_redirect -> stop dummy server"),
- DummyServerPid ! stop,
- tsp("http_redirect -> reset ipfamily option (to inet6fb4)"),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- tsp("http_redirect -> done"),
- ok;
-
- _ ->
- skip("Failed to start local http-server")
- end.
+ URL303 = url(group_name(Config), "/303.html", Config),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL303, []}, [], []),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL303, []}, [], []),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL303, [],"text/plain", "foobar"},
+ [], []).
%%-------------------------------------------------------------------------
-http_redirect_loop(doc) ->
- ["Test redirect loop detection"];
-http_redirect_loop(suite) ->
- [];
-http_redirect_loop(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/redirectloop.html",
-
- {ok, {{_,300,_}, [_ | _], _}}
- = httpc:request(get, {URL, []}, [], []),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+redirect_temporary_redirect() ->
+ [{doc," If the 307 status code is received in response to a request other "
+ "than GET or HEAD, the user agent MUST NOT automatically redirect the request "
+ "unless it can be confirmed by the user, since this might change "
+ "the conditions under which the request was issued."}].
+redirect_temporary_redirect(Config) when is_list(Config) ->
-%%-------------------------------------------------------------------------
-http_internal_server_error(doc) ->
- ["Test 50X codes"];
-http_internal_server_error(suite) ->
- [];
-http_internal_server_error(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL500 = ?URL_START ++ integer_to_list(Port) ++ "/500.html",
-
- {ok, {{_,500,_}, [_ | _], _}}
- = httpc:request(get, {URL500, []}, [], []),
+ URL307 = url(group_name(Config), "/307.html", Config),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL307, []}, [], []),
- URL503 = ?URL_START ++ integer_to_list(Port) ++ "/503.html",
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL307, []}, [], []),
- %% Used to be able to make the service available after retry.
- ets:new(unavailable, [named_table, public, set]),
- ets:insert(unavailable, {503, unavailable}),
-
- {ok, {{_,200, _}, [_ | _], [_|_]}} =
- httpc:request(get, {URL503, []}, [], []),
-
- ets:insert(unavailable, {503, long_unavailable}),
+ {ok, {{_,307,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL307, [],"text/plain", "foobar"},
+ [], []).
- {ok, {{_,503, _}, [_ | _], [_|_]}} =
- httpc:request(get, {URL503, []}, [], []),
+%%-------------------------------------------------------------------------
+redirect_loop() ->
+ [{"doc, Test redirect loop detection"}].
+redirect_loop(Config) when is_list(Config) ->
- ets:delete(unavailable),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ URL = url(group_name(Config), "/redirectloop.html", Config),
+ {ok, {{_,300,_}, [_ | _], _}}
+ = httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
-http_userinfo(doc) ->
- ["Test user info e.i. http://user:passwd@host:port/"];
-http_userinfo(suite) ->
- [];
-http_userinfo(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
+cookie() ->
+ [{doc, "Test cookies."}].
+cookie(Config) when is_list(Config) ->
+ ok = httpc:set_options([{cookies, enabled}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URLAuth = "http://alladin:sesame@localhost:"
- ++ integer_to_list(Port) ++ "/userinfo.html",
-
- {ok, {{_,200,_}, [_ | _], _}}
- = httpc:request(get, {URLAuth, []}, [], []),
+ Request0 = {url(group_name(Config), "/cookie.html", Config), []},
- URLUnAuth = "http://alladin:foobar@localhost:"
- ++ integer_to_list(Port) ++ "/userinfo.html",
-
- {ok, {{_,401, _}, [_ | _], _}} =
- httpc:request(get, {URLUnAuth, []}, [], []),
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-http_cookie(doc) ->
- ["Test cookies."];
-http_cookie(suite) ->
- [];
-http_cookie(Config) when is_list(Config) ->
- ok = httpc:set_options([{cookies, enabled}, {ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URLStart = ?URL_START
- ++ integer_to_list(Port),
-
- URLCookie = URLStart ++ "/cookie.html",
-
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URLCookie, []}, [], []),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, Request0, [], []),
+ %% Populate table to be used by the "dummy" server
ets:new(cookie, [named_table, public, set]),
ets:insert(cookie, {cookies, true}),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URLStart ++ "/", []}, [], []),
-
- ets:delete(cookie),
+ Request1 = {url(group_name(Config), "/", Config), []},
- ok = httpc:set_options([{cookies, disabled}]),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, Request1, [], []),
-%%-------------------------------------------------------------------------
-proxy_options(doc) ->
- ["Perform a OPTIONS request that goes through a proxy."];
-proxy_options(suite) ->
- [];
-proxy_options(Config) when is_list(Config) ->
- %% As of 2011-03-24, erlang.org (which is used as server)
- %% does no longer run Apache, but instead runs inets, which
- %% do not implement "options".
- case ?config(skip, Config) of
- undefined ->
- case httpc:request(options, {?PROXY_URL, []}, [], []) of
- {ok, {{_,200,_}, Headers, _}} ->
- case lists:keysearch("allow", 1, Headers) of
- {value, {"allow", _}} ->
- ok;
- _ ->
- tsf(http_options_request_failed)
- end;
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
+ [{session_cookies, [_|_]}] = httpc:which_cookies(httpc:default_profile()),
-
-%%-------------------------------------------------------------------------
-proxy_head(doc) ->
- ["Perform a HEAD request that goes through a proxy."];
-proxy_head(suite) ->
- [];
-proxy_head(Config) when is_list(Config) ->
- %% As of 2011-03-24, erlang.org (which is used as server)
- %% does no longer run Apache, but instead runs inets.
- case ?config(skip, Config) of
- undefined ->
- case httpc:request(head, {?PROXY_URL, []}, [], []) of
- {ok, {{_,200, _}, [_ | _], []}} ->
- ok;
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
+ ets:delete(cookie),
+ ok = httpc:set_options([{cookies, disabled}]).
-%%-------------------------------------------------------------------------
-proxy_get(doc) ->
- ["Perform a GET request that goes through a proxy."];
-proxy_get(suite) ->
- [];
-proxy_get(Config) when is_list(Config) ->
- case ?config(skip, Config) of
- undefined ->
- case httpc:request(get, {?PROXY_URL, []}, [], []) of
- {ok, {{_,200,_}, [_ | _], Body = [_ | _]}} ->
- inets_test_lib:check_body(Body);
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
%%-------------------------------------------------------------------------
-proxy_emulate_lower_versions(doc) ->
- ["Perform requests as 0.9 and 1.0 clients."];
-proxy_emulate_lower_versions(suite) ->
- [];
-proxy_emulate_lower_versions(Config) when is_list(Config) ->
- case ?config(skip, Config) of
- undefined ->
- Result09 = pelv_get("HTTP/0.9"),
- case Result09 of
- {ok, [_| _] = Body0} ->
- inets_test_lib:check_body(Body0),
- ok;
- _ ->
- tsf({unexpected_result, "HTTP/0.9", Result09})
- end,
-
- %% We do not check the version here as many servers
- %% do not behave according to the rfc and send
- %% 1.1 in its response.
- Result10 = pelv_get("HTTP/1.0"),
- case Result10 of
- {ok,{{_, 200, _}, [_ | _], Body1 = [_ | _]}} ->
- inets_test_lib:check_body(Body1),
- ok;
- _ ->
- tsf({unexpected_result, "HTTP/1.0", Result10})
- end,
-
- Result11 = pelv_get("HTTP/1.1"),
- case Result11 of
- {ok, {{"HTTP/1.1", 200, _}, [_ | _], Body2 = [_ | _]}} ->
- inets_test_lib:check_body(Body2);
- _ ->
- tsf({unexpected_result, "HTTP/1.1", Result11})
- end;
-
- Reason ->
- skip(Reason)
- end.
+cookie_profile() ->
+ [{doc, "Test cookies on a non default profile."}].
+cookie_profile(Config) when is_list(Config) ->
+ inets:start(httpc, [{profile, cookie_test}]),
+ ok = httpc:set_options([{cookies, enabled}], cookie_test),
-pelv_get(Version) ->
- httpc:request(get, {?PROXY_URL, []}, [{version, Version}], []).
+ Request0 = {url(group_name(Config), "/cookie.html", Config), []},
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, Request0, [], [], cookie_test),
-%%-------------------------------------------------------------------------
-proxy_trace(doc) ->
- ["Perform a TRACE request that goes through a proxy."];
-proxy_trace(suite) ->
- [];
-proxy_trace(Config) when is_list(Config) ->
- %%{ok, {{_,200,_}, [_ | _], "TRACE " ++ _}} =
- %% httpc:request(trace, {?PROXY_URL, []}, [], []),
- skip("HTTP TRACE is no longer allowed on the ?PROXY_URL server due "
- "to security reasons").
+ %% Populate table to be used by the "dummy" server
+ ets:new(cookie, [named_table, public, set]),
+ ets:insert(cookie, {cookies, true}),
+ Request1 = {url(group_name(Config), "/", Config), []},
-%%-------------------------------------------------------------------------
-proxy_post(doc) ->
- ["Perform a POST request that goes through a proxy. Note the server"
- " will reject the request this is a test of the sending of the"
- " request."];
-proxy_post(suite) ->
- [];
-proxy_post(Config) when is_list(Config) ->
- %% As of 2011-03-24, erlang.org (which is used as server)
- %% does no longer run Apache, but instead runs inets.
- case ?config(skip, Config) of
- undefined ->
- case httpc:request(post, {?PROXY_URL, [],
- "text/plain", "foobar"}, [],[]) of
- {ok, {{_,405,_}, [_ | _], [_ | _]}} ->
- ok;
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, Request1, [], [], cookie_test),
+ ets:delete(cookie),
+ inets:stop(httpc, cookie_test).
%%-------------------------------------------------------------------------
-proxy_put(doc) ->
- ["Perform a PUT request that goes through a proxy. Note the server"
- " will reject the request this is a test of the sending of the"
- " request."];
-proxy_put(suite) ->
- [];
-proxy_put(Config) when is_list(Config) ->
- %% As of 2011-03-24, erlang.org (which is used as server)
- %% does no longer run Apache, but instead runs inets.
- case ?config(skip, Config) of
- undefined ->
- case httpc:request(put, {"http://www.erlang.org/foobar.html", [],
- "html", "<html> <body><h1> foo </h1>"
- "<p>bar</p> </body></html>"}, [], []) of
- {ok, {{_,405,_}, [_ | _], [_ | _]}} ->
- ok;
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
-
+headers_as_is(doc) ->
+ ["Test the option headers_as_is"];
+headers_as_is(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/dummy.html", Config),
+ {ok, {{_,200,_}, [_|_], [_|_]}} =
+ httpc:request(get, {URL, [{"Host", "localhost"},{"Te", ""}]},
+ [], [{headers_as_is, true}]),
+ {ok, {{_,400,_}, [_|_], [_|_]}} =
+ httpc:request(get, {URL, [{"Te", ""}]},[], [{headers_as_is, true}]).
%%-------------------------------------------------------------------------
-proxy_delete(doc) ->
- ["Perform a DELETE request that goes through a proxy. Note the server"
- " will reject the request this is a test of the sending of the"
- " request. But as the file does not exist the return code will"
- " be 404 not found."];
-proxy_delete(suite) ->
- [];
-proxy_delete(Config) when is_list(Config) ->
- %% As of 2011-03-24, erlang.org (which is used as server)
- %% does no longer run Apache, but instead runs inets.
- case ?config(skip, Config) of
- undefined ->
- URL = ?PROXY_URL ++ "/foobar.html",
- case httpc:request(delete, {URL, []}, [], []) of
- {ok, {{_,404,_}, [_ | _], [_ | _]}} ->
- ok;
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
+userinfo(doc) ->
+ [{doc, "Test user info e.i. http://user:passwd@host:port/"}];
+userinfo(Config) when is_list(Config) ->
+
+ {ok,Host} = inet:gethostname(),
-%%-------------------------------------------------------------------------
-proxy_headers(doc) ->
- ["Use as many request headers as possible"];
-proxy_headers(suite) ->
- [];
-proxy_headers(Config) when is_list(Config) ->
- case ?config(skip, Config) of
- undefined ->
- {ok, {{_,200,_}, [_ | _], [_ | _]}}
- = httpc:request(get, {?PROXY_URL,
- [
- {"Accept",
- "text/*, text/html,"
- " text/html;level=1,"
- " */*"},
- {"Accept-Charset",
- "iso-8859-5, unicode-1-1;"
- "q=0.8"},
- {"Accept-Encoding", "*"},
- {"Accept-Language",
- "sv, en-gb;q=0.8,"
- " en;q=0.7"},
- {"User-Agent", "inets"},
- {"Max-Forwards","5"},
- {"Referer",
- "http://otp.ericsson.se:8000"
- "/product/internal"}
- ]}, [], []),
- ok;
- Reason ->
- skip(Reason)
- end.
+ URLAuth = url(group_name(Config), "alladin:sesame@" ++ Host ++ ":","/userinfo.html", Config),
+ {ok, {{_,200,_}, [_ | _], _}}
+ = httpc:request(get, {URLAuth, []}, [], []),
-%%-------------------------------------------------------------------------
-proxy_auth(doc) ->
- ["Test the code for sending of proxy authorization."];
-proxy_auth(suite) ->
- [];
-proxy_auth(Config) when is_list(Config) ->
- %% Our proxy seems to ignore the header, however our proxy
- %% does not requirer an auth header, but we want to know
- %% atleast the code for sending the header does not crash!
- case ?config(skip, Config) of
- undefined ->
- case httpc:request(get, {?PROXY_URL, []},
- [{proxy_auth, {"foo", "bar"}}], []) of
- {ok, {{_,200, _}, [_ | _], [_|_]}} ->
- ok;
- Unexpected ->
- tsf({unexpected_result, Unexpected})
- end;
- Reason ->
- skip(Reason)
- end.
+ URLUnAuth = url(group_name(Config), "alladin:foobar@" ++ Host ++ ":","/userinfo.html", Config),
+ {ok, {{_,401, _}, [_ | _], _}} =
+ httpc:request(get, {URLUnAuth, []}, [], []).
%%-------------------------------------------------------------------------
-http_server_does_not_exist(doc) ->
- ["Test that we get an error message back when the server "
- "does note exist."];
-http_server_does_not_exist(suite) ->
- [];
-http_server_does_not_exist(Config) when is_list(Config) ->
- {error, _} =
- httpc:request(get, {"http://localhost:" ++
- integer_to_list(?NOT_IN_USE_PORT)
- ++ "/", []},[], []),
- ok.
-
-%%-------------------------------------------------------------------------
page_does_not_exist(doc) ->
["Test that we get a 404 when the page is not found."];
-page_does_not_exist(suite) ->
- [];
page_does_not_exist(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/doesnotexist.html",
- {ok, {{_,404,_}, [_ | _], [_ | _]}}
- = httpc:request(get, {URL, []}, [], []),
- ok.
-
-
+ URL = url(group_name(Config), "/doesnotexist.html", Config),
+ {ok, {{_,404,_}, [_ | _], [_ | _]}}
+ = httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
-proxy_page_does_not_exist(doc) ->
- ["Test that we get a 404 when the page is not found."];
-proxy_page_does_not_exist(suite) ->
- [];
-proxy_page_does_not_exist(Config) when is_list(Config) ->
- case ?config(skip, Config) of
- undefined ->
- URL = ?PROXY_URL ++ "/doesnotexist.html",
- {ok, {{_,404,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, []}, [], []),
- ok;
- Reason ->
- skip(Reason)
- end.
+streaming_error(doc) ->
+ [{doc, "Only async requests can be stremed - Solves OTP-8056"}];
+streaming_error(Config) when is_list(Config) ->
+ Method = get,
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ {error, streaming_error} = httpc:request(Method, Request,
+ [], [{sync, true}, {stream, {self, once}}]),
+ {error, streaming_error} = httpc:request(Method, Request,
+ [], [{sync, true}, {stream, self}]).
%%-------------------------------------------------------------------------
-proxy_https_not_supported(doc) ->
- [];
-proxy_https_not_supported(suite) ->
- [];
-proxy_https_not_supported(Config) when is_list(Config) ->
- Result = httpc:request(get, {"https://login.yahoo.com", []}, [], []),
- case Result of
- {error, https_through_proxy_is_not_currently_supported} ->
- ok;
- _ ->
- tsf({unexpected_reason, Result})
- end.
-
-
+server_does_not_exist(doc) ->
+ [{doc, "Test that we get an error message back when the server "
+ "does note exist."}];
+server_does_not_exist(Config) when is_list(Config) ->
+ {error, _} =
+ httpc:request(get, {"http://localhost:" ++
+ integer_to_list(?NOT_IN_USE_PORT)
+ ++ "/", []},[], []).
%%-------------------------------------------------------------------------
-http_stream(doc) ->
- ["Test the option stream for asynchrony requests"];
-http_stream(suite) ->
- [];
-http_stream(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, {{_,200,_}, [_ | _], Body}} =
- httpc:request(get, {URL, []}, [], []),
-
- {ok, RequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false},
- {stream, self}]),
-
- receive
- {http, {RequestId, stream_start, _Headers}} ->
- ok;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- StreamedBody = receive_streamed_body(RequestId, <<>>),
-
- Body == binary_to_list(StreamedBody).
-
+no_content_204(doc) ->
+ ["Test the case that the HTTP 204 no content header - Solves OTP 6982"];
+no_content_204(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/no_content.html", Config),
+ {ok, {{_,204,_}, [], []}} = httpc:request(URL).
%%-------------------------------------------------------------------------
-http_stream_once(doc) ->
- ["Test the option stream for asynchrony requests"];
-http_stream_once(suite) ->
- [];
-http_stream_once(Config) when is_list(Config) ->
- p("http_stream_once -> entry with"
- "~n Config: ~p", [Config]),
-
- p("http_stream_once -> set ipfamily to inet", []),
- ok = httpc:set_options([{ipfamily, inet}]),
- p("http_stream_once -> start dummy server", []),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- PortStr = integer_to_list(Port),
- p("http_stream_once -> once", []),
- once(?URL_START ++ PortStr ++ "/once.html"),
- p("http_stream_once -> once_chunked", []),
- once(?URL_START ++ PortStr ++ "/once_chunked.html"),
- p("http_stream_once -> dummy", []),
- once(?URL_START ++ PortStr ++ "/dummy.html"),
-
- p("http_stream_once -> stop dummy server", []),
- DummyServerPid ! stop,
- p("http_stream_once -> set ipfamily to inet6fb4", []),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- p("http_stream_once -> done", []),
- ok.
-
-once(URL) ->
- p("once -> issue sync request for ~p", [URL]),
- {ok, {{_,200,_}, [_ | _], Body}} =
- httpc:request(get, {URL, []}, [], []),
-
- p("once -> issue async (self stream) request for ~p", [URL]),
- {ok, RequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false},
- {stream, {self, once}}]),
-
- p("once -> await stream_start reply for (async) request ~p", [RequestId]),
- NewPid =
- receive
- {http, {RequestId, stream_start, _Headers, Pid}} ->
- p("once -> received stream_start reply for (async) request ~p: ~p",
- [RequestId, Pid]),
- Pid;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- tsp("once -> request handler: ~p", [NewPid]),
-
- p("once -> await stream reply for (async) request ~p", [RequestId]),
- BodyPart =
- receive
- {http, {RequestId, stream, BinBodyPart}} ->
- p("once -> received stream reply for (async) request ~p: "
- "~n~p", [RequestId, binary_to_list(BinBodyPart)]),
- BinBodyPart
- end,
-
- tsp("once -> first body part '~p' received", [binary_to_list(BodyPart)]),
-
- StreamedBody = receive_streamed_body(RequestId, BinBodyPart, NewPid),
-
- Body = binary_to_list(StreamedBody),
-
- p("once -> done when Bode: ~p", [Body]),
- ok.
-
-
+tolerate_missing_CR() ->
+ [{doc, "Test the case that the HTTP server uses only LF instead of CRLF"
+ "as delimitor. Solves OTP-7304"}].
+tolerate_missing_CR(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/missing_CR.html", Config),
+ {ok, {{_,200,_}, _, [_ | _]}} = httpc:request(URL).
%%-------------------------------------------------------------------------
-proxy_stream(doc) ->
- ["Test the option stream for asynchrony requests"];
-proxy_stream(suite) ->
- [];
-proxy_stream(Config) when is_list(Config) ->
- case ?config(skip, Config) of
- undefined ->
- {ok, {{_,200,_}, [_ | _], Body}} =
- httpc:request(get, {?PROXY_URL, []}, [], []),
-
- {ok, RequestId} =
- httpc:request(get, {?PROXY_URL, []}, [],
- [{sync, false}, {stream, self}]),
-
- receive
- {http, {RequestId, stream_start, _Headers}} ->
- ok;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- StreamedBody = receive_streamed_body(RequestId, <<>>),
-
- Body == binary_to_list(StreamedBody);
- Reason ->
- skip(Reason)
- end.
-
-
-%%-------------------------------------------------------------------------
-parse_url(doc) ->
- ["Test that an url is parsed correctly"];
-parse_url(suite) ->
- [];
-parse_url(Config) when is_list(Config) ->
- %% ipv6
- {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
- {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
- [{ipv6_host_with_brackets, true}]),
- {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
- [{ipv6_host_with_brackets, false}]),
- {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
- [{foo, false}]),
- {error,
- {malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
- http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
-
- %% ipv4
- {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
- http_uri:parse("http://127.0.0.1/foobar.html"),
-
- %% host
- {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://localhost:8888/foobar.html"),
-
- %% Userinfo
- {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
-
- %% Scheme error
- {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
- {error, {malformed_url, _, _}} =
- http_uri:parse("localhost:8888/foobar.html"),
-
- %% Query
- {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
- http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
-
- %% Esc chars
- {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
- http_uri:parse("http://www.somedomain.com/%2Eabc"),
- {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
- http_uri:parse("http://www.somedomain.com/%252Eabc"),
- {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
- http_uri:parse("http://www.somedomain.com/%25abc"),
- {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
- http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
-
-
- ok.
+empty_body() ->
+ [{doc, "An empty body was not returned directly. There was a delay for several"
+ "seconds. Solves OTP-6243."}].
+empty_body(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/empty.html", Config),
+ {ok, {{_,200,_}, [_ | _], []}} =
+ httpc:request(get, {URL, []}, [{timeout, 500}], []).
%%-------------------------------------------------------------------------
-ipv6_ipcomm() ->
- [{require, ipv6_hosts}].
-ipv6_ipcomm(doc) ->
- ["Test ip_comm ipv6."];
-ipv6_ipcomm(suite) ->
- [];
-ipv6_ipcomm(Config) when is_list(Config) ->
- HTTPOptions = [],
- SocketType = ip_comm,
- Scheme = "http",
- Extra = [],
- ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
-
+transfer_encoding() ->
+ [{doc, "Transfer encoding is case insensitive. Solves OTP-6807"}].
+transfer_encoding(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/capital_transfer_encoding.html", Config),
+ {ok, {{_,200,_}, [_|_], [_ | _]}} = httpc:request(URL).
%%-------------------------------------------------------------------------
-ipv6_essl() ->
- [{require, ipv6_hosts}].
-ipv6_essl(doc) ->
- ["Test essl ipv6."];
-ipv6_essl(suite) ->
- [];
-ipv6_essl(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig = {essl, SSLOptions},
- tsp("ssl_ipv6 -> make request using: "
- "~n SSLOptions: ~p", [SSLOptions]),
- HTTPOptions = [{ssl, SSLConfig}],
- SocketType = essl,
- Scheme = "https",
- Extra = SSLOptions,
- ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
-
+empty_response_header() ->
+ [{doc, "Test the case that the HTTP server does not send any headers. Solves OTP-6830"}].
+empty_response_header(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/no_headers.html", Config),
+ {ok, {{_,200,_}, [], [_ | _]}} = httpc:request(URL).
%%-------------------------------------------------------------------------
-ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
- %% Check if we are a IPv6 host
- tsp("ipv6 -> verify ipv6 support"),
- case inets_test_lib:has_ipv6_support(Config) of
- {ok, Addr} ->
- tsp("ipv6 -> ipv6 supported: ~p", [Addr]),
- {DummyServerPid, Port} = dummy_server(SocketType, ipv6, Extra),
- Profile = ?config(profile, Config),
- URL =
- Scheme ++
- "://[" ++ http_transport:ipv6_name(Addr) ++ "]:" ++
- integer_to_list(Port) ++ "/foobar.html",
- tsp("ipv6 -> issue request with: "
- "~n URL: ~p"
- "~n HTTPOptions: ~p", [URL, HTTPOptions]),
- case httpc:request(get, {URL, []}, HTTPOptions, [], Profile) of
- {ok, {{_,200,_}, [_ | _], [_|_]}} ->
- tsp("ipv6 -> expected result"),
- DummyServerPid ! stop,
- ok;
- {ok, Unexpected} ->
- tsp("ipv6 -> unexpected result: "
- "~n ~p", [Unexpected]),
- DummyServerPid ! stop,
- tsf({unexpected_result, Unexpected});
- {error, Reason} ->
- tsp("ipv6 -> error: "
- "~n Reason: ~p", [Reason]),
- DummyServerPid ! stop,
- tsf(Reason)
- end,
- ok;
- _ ->
- tsp("ipv6 -> ipv6 not supported"),
- skip("Host does not support IPv6")
- end.
-
+bad_response(doc) ->
+ [{doc, "Test what happens when the server does not follow the protocol"}];
-%%-------------------------------------------------------------------------
+bad_response(Config) when is_list(Config) ->
-headers_as_is(doc) ->
- ["Test the option headers_as_is"];
-headers_as_is(suite) ->
- [];
-headers_as_is(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, {{_,200,_}, [_|_], [_|_]}} =
- httpc:request(get, {URL, [{"Host", "localhost"},{"Te", ""}]},
- [], [{headers_as_is, true}]),
-
- {ok, {{_,400,_}, [_|_], [_|_]}} =
- httpc:request(get, {URL, [{"Te", ""}]},[], [{headers_as_is, true}]),
- ok.
+ URL0 = url(group_name(Config), "/missing_crlf.html", Config),
+ URL1 = url(group_name(Config), "/wrong_statusline.html", Config),
+ {error, timeout} = httpc:request(get, {URL0, []}, [{timeout, 400}], []),
+ {error, Reason} = httpc:request(URL1),
+ ct:print("Wrong Statusline: ~p~n", [Reason]).
%%-------------------------------------------------------------------------
-selecting_session(doc) ->
- ["Test selection of sessions - OTP-9847"];
-selecting_session(suite) ->
- [];
-selecting_session(Config) when is_list(Config) ->
- tsp("selecting_session -> entry with"
- "~n Config: ~p", [Config]),
-
- tsp("selecting_session -> set ipfamily to inet"),
- ok = httpc:set_options([{ipfamily, inet}]),
-
- tsp("selecting_session -> start server"),
- {ServerPid, Port} = otp_9847_server(),
-
- PortStr = integer_to_list(Port),
- URL = ?URL_START ++ PortStr ++ "/index.html",
-
- tsp("selecting_session -> issue the first batch (three) requests"),
- lists:foreach(fun(P) ->
- tsp("selecting_session:fun1 -> "
- "send stop request to ~p", [P]),
- P ! stop
- end,
- reqs(URL, ServerPid, 3, 3, false)),
- tsp("selecting_session -> sleep some (1) to make sure nothing lingers"),
- ?SLEEP(5000),
- tsp("selecting_session -> "
- "instruct the server to reply to the first request"),
- ServerPid ! {answer, true},
- receive
- {answer, true} ->
- tsp("selecting_session -> "
- "received ack from server to reply to the first request"),
- ok
- end,
- tsp("selecting_session -> issue the second batch (four) requests"),
- lists:foreach(fun(P) ->
- tsp("selecting_session:fun2 -> "
- "send stop request to ~p", [P]),
- P ! stop
- end,
- reqs(URL, ServerPid, 4, 1, true)),
- tsp("selecting_session -> sleep some (2) to make sure nothing lingers"),
- ?SLEEP(5000),
-
- tsp("selecting_session -> stop server"),
- ServerPid ! stop,
- tsp("selecting_session -> set ipfamily (back) to inet6fb4"),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- tsp("selecting_session -> done"),
- ok.
-
-reqs(URL, ServerPid, NumReqs, NumHandlers, InitialSync) ->
- tsp("reqs -> entry with"
- "~n URL: ~p"
- "~n ServerPid: ~w"
- "~n NumReqs: ~w"
- "~n NumHandlers: ~w"
- "~n InitialSync: ~w",
- [URL, ServerPid, NumReqs, NumHandlers, InitialSync]),
- Handlers = reqs2(URL, NumReqs, [], InitialSync),
- tsp("reqs -> "
- "~n Handlers: ~w", [Handlers]),
- case length(Handlers) of
- NumHandlers ->
- tsp("reqs -> "
- "~n NumHandlers: ~w", [NumHandlers]),
- ServerPid ! num_handlers,
- receive
- {num_handlers, NumHandlers} ->
- tsp("reqs -> received num_handlers with"
- "~n NumHandlers: ~w", [NumHandlers]),
- Handlers;
- {num_handlers, WrongNumHandlers} ->
- tsp("reqs -> received num_handlers with"
- "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
- exit({wrong_num_handlers1, WrongNumHandlers, NumHandlers})
- end;
- WrongNumHandlers ->
- tsp("reqs -> "
- "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
- exit({wrong_num_handlers2, WrongNumHandlers, NumHandlers})
- end.
-
-
-reqs2(_URL, 0, Acc, _Sync) ->
- lists:reverse(Acc);
-reqs2(URL, Num, Acc, Sync) ->
- tsp("reqs2 -> entry with"
- "~n Num: ~w"
- "~n Sync: ~w", [Num, Sync]),
- case httpc:request(get, {URL, []}, [], [{sync, Sync}]) of
- {ok, _Reply} ->
- tsp("reqs2 -> successful request: ~p", [_Reply]),
- receive
- {handler, Handler, _Manager} ->
- %% This is when a new handler is created
- tsp("reqs2 -> received handler: ~p", [Handler]),
- case lists:member(Handler, Acc) of
- true ->
- tsp("reqs2 -> duplicate handler"),
- exit({duplicate_handler, Handler, Num, Acc});
- false ->
- tsp("reqs2 -> wait for data ack"),
- receive
- {data_received, Handler} ->
- tsp("reqs2 -> "
- "received data ack from ~p", [Handler]),
- case Sync of
- true ->
- reqs2(URL, Num-1, [Handler|Acc],
- false);
- false ->
- reqs2(URL, Num-1, [Handler|Acc],
- Sync)
- end
- end
- end;
-
- {data_received, Handler} ->
- tsp("reqs2 -> "
- "received data ack from ~p", [Handler]),
- reqs2(URL, Num-1, Acc, false)
-
- end;
-
- {error, Reason} ->
- tsp("reqs2 -> request ~w failed: ~p", [Num, Reason]),
- exit({request_failed, Reason, Num, Acc})
- end.
-
-otp_9847_server() ->
- TC = self(),
- Pid = spawn_link(fun() -> otp_9847_server_init(TC) end),
- receive
- {port, Port} ->
- {Pid, Port}
- end.
-
-otp_9847_server_init(TC) ->
- tsp("otp_9847_server_init -> entry with"
- "~n TC: ~p", [TC]),
- {ok, ListenSocket} =
- gen_tcp:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}]),
- tsp("otp_9847_server_init -> listen socket created: "
- "~n ListenSocket: ~p", [ListenSocket]),
- {ok, Port} = inet:port(ListenSocket),
- tsp("otp_9847_server_init -> Port: ~p", [Port]),
- TC ! {port, Port},
- otp_9847_server_main(TC, ListenSocket, false, []).
-
-otp_9847_server_main(TC, ListenSocket, Answer, Handlers) ->
- tsp("otp_9847_server_main -> entry with"
- "~n TC: ~p"
- "~n ListenSocket: ~p"
- "~n Answer: ~p"
- "~n Handlers: ~p", [TC, ListenSocket, Answer, Handlers]),
- case gen_tcp:accept(ListenSocket, 1000) of
- {ok, Sock} ->
- tsp("otp_9847_server_main -> accepted"
- "~n Sock: ~p", [Sock]),
- {Handler, Mon, Port} = otp_9847_handler(TC, Sock, Answer),
- tsp("otp_9847_server_main -> handler ~p created for ~w",
- [Handler, Port]),
- gen_tcp:controlling_process(Sock, Handler),
- tsp("otp_9847_server_main -> control transfer"),
- Handler ! owner,
- tsp("otp_9847_server_main -> "
- "handler ~p informed of owner transfer", [Handler]),
- TC ! {handler, Handler, self()},
- tsp("otp_9847_server_main -> "
- "TC ~p informed of handler ~p", [TC, Handler]),
- otp_9847_server_main(TC, ListenSocket, Answer,
- [{Handler, Mon, Sock, Port}|Handlers]);
-
- {error, timeout} ->
- tsp("otp_9847_server_main -> timeout"),
- receive
- {answer, true} ->
- tsp("otp_9847_server_main -> received answer request"),
- TC ! {answer, true},
- otp_9847_server_main(TC, ListenSocket, true, Handlers);
-
- {'DOWN', _Mon, process, Pid, _Reason} ->
- %% Could be one of the handlers
- tsp("otp_9847_server_main -> received DOWN for ~p", [Pid]),
- otp_9847_server_main(TC, ListenSocket, Answer,
- lists:keydelete(Pid, 1, Handlers));
-
- num_handlers ->
- tsp("otp_9847_server_main -> "
- "received request for number of handlers (~w)",
- [length(Handlers)]),
- TC ! {num_handlers, length(Handlers)},
- otp_9847_server_main(TC, ListenSocket, Answer, Handlers);
+internal_server_error(doc) ->
+ ["Test 50X codes"];
+internal_server_error(Config) when is_list(Config) ->
- stop ->
- tsp("otp_9847_server_main -> received stop request"),
- %% Stop all handlers (just in case)
- Pids = [Handler || {Handler, _, _} <- Handlers],
- lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
- exit(normal);
+ URL500 = url(group_name(Config), "/500.html", Config),
- Any ->
- tsp("otp_9847_server_main -> received"
- "~n Any: ~p", [Any]),
- exit({crap, Any})
+ {ok, {{_,500,_}, [_ | _], _}}
+ = httpc:request(get, {URL500, []}, [], []),
- after 0 ->
- tsp("otp_9847_server_main -> nothing in queue"),
- otp_9847_server_main(TC, ListenSocket, Answer, Handlers)
- end;
+ URL503 = url(group_name(Config), "/503.html", Config),
- Error ->
- exit(Error)
- end.
+ %% Used to be able to make the service available after retry.
+ ets:new(unavailable, [named_table, public, set]),
+ ets:insert(unavailable, {503, unavailable}),
+ {ok, {{_,200, _}, [_ | _], [_|_]}} =
+ httpc:request(get, {URL503, []}, [], []),
-otp_9847_handler(TC, Sock, Answer) ->
- tsp("otp_9847_handler -> entry with"
- "~n TC: ~p"
- "~n Sock: ~p"
- "~n Answer: ~p", [TC, Sock, Answer]),
- Self = self(),
- {Pid, Mon} =
- spawn_opt(fun() ->
- otp_9847_handler_init(TC, Self, Sock, Answer)
- end,
- [monitor]),
- receive
- {port, Port} ->
- tsp("otp_9847_handler -> received port message (from ~p)"
- "~n Port: ~p", [Pid, Port]),
- {Pid, Mon, Port}
- end.
-
+ ets:insert(unavailable, {503, long_unavailable}),
-otp_9847_handler_init(TC, Server, Sock, Answer) ->
- tsp("otp_9847_handler_init -> entry with"
- "~n TC: ~p"
- "~n Server: ~p"
- "~n Sock: ~p"
- "~n Answer: ~p", [TC, Server, Sock, Answer]),
- {ok, Port} = inet:port(Sock),
- Server ! {port, Port},
- receive
- owner ->
- tsp("otp_9847_handler_init -> "
- "received owner message - activate socket"),
- inet:setopts(Sock, [{active, true}]),
- otp_9847_handler_main(TC, Server, Sock, Answer, [?HTTP_MAX_HEADER_SIZE])
- end.
-
-otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs) ->
- tsp("otp_9847_handler_main -> entry with"
- "~n TC: ~p"
- "~n Server: ~p"
- "~n Sock: ~p"
- "~n Answer: ~p"
- "~n ParseArgs: ~p", [TC, Server, Sock, Answer, ParseArgs]),
- receive
- stop ->
- tsp("otp_9847_handler_main -> received stop request"),
- exit(normal);
-
- {tcp, Sock, _Data} when Answer =:= false ->
- tsp("otp_9847_handler_main -> received tcp data - no answer"),
- TC ! {data_received, self()},
- inet:setopts(Sock, [{active, true}]),
- %% Ignore all data
- otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs);
-
- {tcp, Sock, Data} when Answer =:= true ->
- tsp("otp_9847_handler_main -> received tcp data - answer"),
- TC ! {data_received, self()},
- inet:setopts(Sock, [{active, true}]),
- NewParseArgs = otp_9847_handler_request(Sock, [Data|ParseArgs]),
- otp_9847_handler_main(TC, Server, Sock, Answer, NewParseArgs);
-
- {tcp_closed, Sock} ->
- tsp("otp_9847_handler_main -> received tcp socket closed"),
- exit(normal);
-
- {tcp_error, Sock, Reason} ->
- tsp("otp_9847_handler_main -> socket error: ~p", [Reason]),
- (catch gen_tcp:close(Sock)),
- exit(normal)
-
- %% after 30000 ->
- %% gen_tcp:close(Sock),
- %% exit(normal)
- end.
-
-otp_9847_handler_request(Sock, Args) ->
- Msg =
- case httpd_request:parse(Args) of
- {ok, {_, "/index.html" = _RelUrl, _, _, _}} ->
- B =
- "<HTML><BODY>" ++
- "...some body part..." ++
- "</BODY></HTML>",
- Len = integer_to_list(length(B)),
- "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
- end,
- gen_tcp:send(Sock, Msg),
- [?HTTP_MAX_HEADER_SIZE].
-
+ {ok, {{_,503, _}, [_ | _], [_|_]}} =
+ httpc:request(get, {URL503, []}, [], []),
+ ets:delete(unavailable).
%%-------------------------------------------------------------------------
-options(doc) ->
- ["Test the option parameters."];
-options(suite) ->
+invalid_http(doc) ->
+ ["Test parse error"];
+invalid_http(suite) ->
[];
-options(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, {{_,200,_}, [_ | _], Bin}}
- = httpc:request(get, {URL, []}, [{foo, bar}],
- %% Ignore unknown options
- [{body_format, binary}, {foo, bar}]),
-
- true = is_binary(Bin),
- {ok, {200, [_|_]}}
- = httpc:request(get, {URL, []}, [{timeout, infinity}],
- [{full_result, false}]);
- _ ->
- skip("Failed to start local http-server")
- end.
-
+invalid_http(Config) when is_list(Config) ->
-%%-------------------------------------------------------------------------
+ URL = url(group_name(Config), "/invalid_http.html", Config),
-http_invalid_http(doc) ->
- ["Test parse error"];
-http_invalid_http(suite) ->
- [];
-http_invalid_http(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/invalid_http.html",
-
{error, {could_not_parse_as_http, _} = Reason} =
httpc:request(get, {URL, []}, [], []),
-
- test_server:format("Parse error: ~p ~n", [Reason]),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ ct:print("Parse error: ~p ~n", [Reason]).
%%-------------------------------------------------------------------------
+emulate_lower_versions(doc) ->
+ [{doc, "Perform request as 0.9 and 1.0 clients."}];
+emulate_lower_versions(Config) when is_list(Config) ->
--define(GOOGLE, "www.google.com").
-
-hexed_query_otp_6191(doc) ->
- [];
-hexed_query_otp_6191(suite) ->
- [];
-hexed_query_otp_6191(Config) when is_list(Config) ->
- Google = ?GOOGLE,
- GoogleSearch = "http://" ++ Google ++ "/search",
- Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
- URI1 = GoogleSearch ++ Search1,
- Search2 = "?hl=en&q=%25%25",
- URI2 = GoogleSearch ++ Search2,
- Search3 = "?hl=en&q=%foo",
- URI3 = GoogleSearch ++ Search3,
-
- Verify1 =
- fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
- (_) -> error
- end,
- Verify2 = Verify1,
- Verify3 = Verify1,
- verify_uri(URI1, Verify1),
- verify_uri(URI2, Verify2),
- verify_uri(URI3, Verify3),
- ok.
-
-verify_uri(URI, Verify) ->
- case http_uri:parse(URI) of
- {ok, ParsedURI} ->
- case Verify(ParsedURI) of
- ok ->
- ok;
- error ->
- Reason = {unexpected_parse_result, URI, ParsedURI},
- ERROR = {error, Reason},
- throw(ERROR)
- end;
- {error, _} = ERROR ->
- throw(ERROR)
- end.
+ URL = url(group_name(Config), "/dummy.html", Config),
+ {ok, Body0} =
+ httpc:request(get, {URL, []}, [{version, "HTTP/0.9"}], []),
+ inets_test_lib:check_body(Body0),
+ {ok, {{"HTTP/1.0", 200, _}, [_ | _], Body1 = [_ | _]}} =
+ httpc:request(get, {URL, []}, [{version, "HTTP/1.0"}], []),
+ inets_test_lib:check_body(Body1),
+ {ok, {{"HTTP/1.1", 200, _}, [_ | _], Body2 = [_ | _]}} =
+ httpc:request(get, {URL, []}, [{version, "HTTP/1.1"}], []),
+ inets_test_lib:check_body(Body2).
%%-------------------------------------------------------------------------
-empty_body_otp_6243(doc) ->
- ["An empty body was not returned directly. There was a delay for several"
- "seconds."];
-empty_body_otp_6243(suite) ->
- [];
-empty_body_otp_6243(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/empty.html",
- {ok, {{_,200,_}, [_ | _], []}} =
- httpc:request(get, {URL, []}, [{timeout, 500}], []).
+relaxed(doc) ->
+ ["Test relaxed mode"];
+relaxed(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/missing_reason_phrase.html", Config),
-%%-------------------------------------------------------------------------
+ {error, Reason} =
+ httpc:request(get, {URL, []}, [{relaxed, false}], []),
-transfer_encoding_otp_6807(doc) ->
- ["Transfer encoding is case insensitive"];
-transfer_encoding_otp_6807(suite) ->
- [];
-transfer_encoding_otp_6807(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++
- "/capital_transfer_encoding.html",
- {ok, {{_,200,_}, [_|_], [_ | _]}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ ct:print("Not relaxed: ~p~n", [Reason]),
+ {ok, {{_, 200, _}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, []}, [{relaxed, true}], []).
%%-------------------------------------------------------------------------
-proxy_not_modified_otp_6821(doc) ->
- ["If unmodified no body should be returned"];
-proxy_not_modified_otp_6821(suite) ->
- [];
-proxy_not_modified_otp_6821(Config) when is_list(Config) ->
- case ?config(skip, Config) of
- undefined ->
- provocate_not_modified_bug(?PROXY_URL);
- Reason ->
- skip(Reason)
- end.
+headers() ->
+ [{doc,"Use as many request headers as possible not used in proxy_headers"}].
+headers(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/dummy.html", Config),
+ DocRoot = ?config(doc_root, Config),
-%%-------------------------------------------------------------------------
+ {ok, FileInfo} =
+ file:read_file_info(filename:join([DocRoot,"dummy.html"])),
+ CreatedSec =
+ calendar:datetime_to_gregorian_seconds(
+ FileInfo#file_info.mtime),
-empty_response_header_otp_6830(doc) ->
- ["Test the case that the HTTP server does not send any headers"];
-empty_response_header_otp_6830(suite) ->
- [];
-empty_response_header_otp_6830(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/no_headers.html",
- {ok, {{_,200,_}, [], [_ | _]}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ Mod = httpd_util:rfc1123_date(
+ calendar:gregorian_seconds_to_datetime(
+ CreatedSec-1)),
+ Date = httpd_util:rfc1123_date({date(), time()}),
-%%-------------------------------------------------------------------------
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, [{"If-Modified-Since",
+ Mod},
+ {"From","[email protected]"},
+ {"Date", Date}
+ ]}, [], []),
-no_content_204_otp_6982(doc) ->
- ["Test the case that the HTTP 204 no content header"];
-no_content_204_otp_6982(suite) ->
- [];
-no_content_204_otp_6982(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/no_content.html",
- {ok, {{_,204,_}, [], []}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ Mod1 = httpd_util:rfc1123_date(
+ calendar:gregorian_seconds_to_datetime(
+ CreatedSec+1)),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, [{"If-UnModified-Since",
+ Mod1}
+ ]}, [], []),
-%%-------------------------------------------------------------------------
+ Tag = httpd_util:create_etag(FileInfo),
-missing_CR_otp_7304(doc) ->
- ["Test the case that the HTTP server uses only LF instead of CRLF"
- "as delimitor"];
-missing_CR_otp_7304(suite) ->
- [];
-missing_CR_otp_7304(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_CR.html",
- {ok, {{_,200,_}, _, [_ | _]}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, [{"If-Match",
+ Tag}
+ ]}, [], []),
+ {ok, {{_,200,_}, [_ | _], _}} =
+ httpc:request(get, {URL, [{"If-None-Match",
+ "NotEtag,NeihterEtag"},
+ {"Connection", "Close"}
+ ]}, [], []).
%%-------------------------------------------------------------------------
+headers_dummy() ->
+ ["Test the code for handling headers we do not want/can send "
+ "to a real server. Note it is not logical to send"
+ "all of these headers together, we only want to test that"
+ "the code for handling headers will not crash."].
+headers_dummy(Config) when is_list(Config) ->
-otp_7883_1(doc) ->
- ["OTP-7883-sync"];
-otp_7883_1(suite) ->
- [];
-otp_7883_1(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
-
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
- {error, socket_closed_remotely} = httpc:request(URL),
- DummyServerPid ! stop,
-
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ URL = url(group_name(Config), "/dummy_headers.html", Config),
-otp_7883_2(doc) ->
- ["OTP-7883-async"];
-otp_7883_2(suite) ->
- [];
-otp_7883_2(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
+ Foo = http_chunk:encode("foobar") ++
+ binary_to_list(http_chunk:encode_last()),
+ FooBar = Foo ++ "\r\n\r\nOther:inets_test\r\n\r\n",
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
- Method = get,
- Request = {URL, []},
- HttpOptions = [],
- Options = [{sync, false}],
- Profile = httpc:default_profile(),
- {ok, RequestId} =
- httpc:request(Method, Request, HttpOptions, Options, Profile),
- ok =
- receive
- {http, {RequestId, {error, socket_closed_remotely}}} ->
- ok
- end,
- DummyServerPid ! stop,
+ UserPasswd = base64:encode_to_string("Alladin:Sesame"),
+ Auth = "Basic " ++ UserPasswd,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
+ %% The dummy server will ignore the headers, we only want to test
+ %% that the client header-handling code. This would not
+ %% be a vaild http-request!
+ {ok, {{_,200,_}, [_ | _], [_|_]}} =
+ httpc:request(post,
+ {URL,
+ [{"Via",
+ "1.0 fred, 1.1 nowhere.com (Apache/1.1)"},
+ {"Warning","1#pseudonym foobar"},
+ {"Vary","*"},
+ {"Upgrade","HTTP/2.0"},
+ {"Pragma", "1#no-cache"},
+ {"Cache-Control", "no-cache"},
+ {"Connection", "close"},
+ {"Date", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"Accept", " text/plain; q=0.5, text/html"},
+ {"Accept-Language", "en"},
+ {"Accept-Encoding","chunked"},
+ {"Accept-Charset", "ISO8859-1"},
+ {"Authorization", Auth},
+ {"Expect", "1#100-continue"},
+ {"User-Agent","inets"},
+ {"Transfer-Encoding","chunked"},
+ {"Range", " bytes=0-499"},
+ {"If-Range", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"If-Match", "*"},
+ {"Content-Type", "text/plain"},
+ {"Content-Encoding", "chunked"},
+ {"Content-Length", "6"},
+ {"Content-Language", "en"},
+ {"Content-Location", "http://www.foobar.se"},
+ {"Content-MD5",
+ "104528739076276072743283077410617235478"},
+ {"Content-Range", "bytes 0-499/1234"},
+ {"Allow", "GET"},
+ {"Proxy-Authorization", Auth},
+ {"Expires", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"Upgrade", "HTTP/2.0"},
+ {"Last-Modified", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"Trailer","1#User-Agent"}
+ ], "text/plain", FooBar},
+ [], []).
%%-------------------------------------------------------------------------
+invalid_headers(Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]},
+ {error, _} = httpc:request(get, Request, [], []).
-otp_8154_1(doc) ->
- ["OTP-8154"];
-otp_8154_1(suite) ->
- [];
-otp_8154_1(Config) when is_list(Config) ->
- start_inets(),
- ReqSeqNumServer = start_sequence_number_server(),
- RespSeqNumServer = start_sequence_number_server(),
- {ok, Server, Port} = start_slow_server(RespSeqNumServer),
- Clients = run_clients(105, Port, ReqSeqNumServer),
- %% ok = wait_for_clients(Clients),
- ok = wait4clients(Clients, timer:minutes(3)),
- Server ! shutdown,
- RespSeqNumServer ! shutdown,
- ReqSeqNumServer ! shutdown,
- ok.
-
-start_inets() ->
- inets:start(),
- ok.
-
-
-%% -----------------------------------------------------
-%% A sequence number handler
-%% The purpose is to be able to pair requests with responses.
-
-start_sequence_number_server() ->
- proc_lib:spawn(fun() -> loop_sequence_number(1) end).
-
-loop_sequence_number(N) ->
- receive
- shutdown ->
- ok;
- {From, get_next} ->
- From ! {next_is, N},
- loop_sequence_number(N + 1)
- end.
-
-get_next_sequence_number(SeqNumServer) ->
- SeqNumServer ! {self(), get_next},
- receive {next_is, N} -> N end.
-
-%% -----------------------------------------------------
-%% Client part
-%% Sends requests randomly parallel
-
-run_clients(NumClients, ServerPort, SeqNumServer) ->
- io:format("start clients when"
- "~n NumClients: ~w"
- "~n ServerPort: ~w"
- "~n SeqNumServer: ~w"
- "~n", [NumClients, ServerPort, SeqNumServer]),
- set_random_seed(),
- lists:map(
- fun(Id) ->
- io:format("starting client ~w~n", [Id]),
- Req = f("req~3..0w", [get_next_sequence_number(SeqNumServer)]),
- Url = f(?URL_START ++ "~w/~s", [ServerPort, Req]),
- Pid = proc_lib:spawn(
- fun() ->
- io:format("[~w] client started - "
- "issue request~n", [Id]),
- case httpc:request(Url) of
- {ok, {{_,200,_}, _, Resp}} ->
- io:format("[~w] 200 response: "
- "~p~n", [Id, Resp]),
- case lists:prefix(Req++"->", Resp) of
- true -> exit(normal);
- false -> exit({bad_resp,Req,Resp})
- end;
- {ok, {{_,EC,Reason},_,Resp}} ->
- io:format("[~w] ~w response: "
- "~s~n~s~n",
- [Id, EC, Reason, Resp]),
- exit({bad_resp,Req,Resp});
- Crap ->
- io:format("[~w] bad response: ~p",
- [Id, Crap]),
- exit({bad_resp, Req, Crap})
- end
- end),
- MRef = erlang:monitor(process, Pid),
- timer:sleep(10 + random:uniform(1334)),
- {Id, Pid, MRef}
-
- end,
- lists:seq(1, NumClients)).
-
-%% wait_for_clients(Clients) ->
-%% lists:foreach(
-%% fun({Id, Pid, MRef}) ->
-%% io:format("waiting for client ~w termination~n", [Id]),
-%% receive
-%% {'DOWN', MRef, process, Pid, normal} ->
-%% io:format("waiting for clients: "
-%% "normal exit from ~w (~p)~n",
-%% [Id, Pid]),
-%% ok;
-%% {'DOWN', MRef, process, Pid, Reason} ->
-%% io:format("waiting for clients: "
-%% "unexpected exit from ~w (~p):"
-%% "~n Reason: ~p"
-%% "~n", [Id, Pid, Reason]),
-%% erlang:error(Reason)
-%% end
-%% end,
-%% Clients).
-
+remote_socket_close(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/just_close.html", Config),
+ {error, socket_closed_remotely} = httpc:request(URL).
-wait4clients([], _Timeout) ->
- ok;
-wait4clients(Clients, Timeout) when Timeout > 0 ->
- io:format("wait4clients -> entry with"
- "~n length(Clients): ~w"
- "~n Timeout: ~w"
- "~n", [length(Clients), Timeout]),
- T = t(),
- receive
- {'DOWN', _MRef, process, Pid, normal} ->
- case lists:keysearch(Pid, 2, Clients) of
- {value, {Id, _, _}} ->
- io:format("receive normal exit message "
- "from client ~p (~p)", [Id, Pid]),
- NewClients =
- lists:keydelete(Id, 1, Clients),
- wait4clients(NewClients,
- Timeout - (t() - T));
- false ->
- io:format("receive normal exit message "
- "from unknown process: ~p", [Pid]),
- wait4clients(Clients, Timeout - (t() - T))
- end;
-
- {'DOWN', _MRef, process, Pid, Reason} ->
- case lists:keysearch(Pid, 2, Clients) of
- {value, {Id, _, _}} ->
- io:format("receive bad exit message "
- "from client ~p (~p):"
- "~n ~p", [Id, Pid, Reason]),
- erlang:error({bad_client_termination, Id, Reason});
- false ->
- io:format("receive normal exit message "
- "from unknown process: ~p", [Pid]),
- wait4clients(Clients, Timeout - (t() - T))
- end
-
- after Timeout ->
- erlang:error({client_timeout, Clients})
- end;
-wait4clients(Clients, _) ->
- erlang:error({client_timeout, Clients}).
-
-
-%% Time in milli seconds
-t() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
-
-%% -----------------------------------------------------
-%% Webserver part:
-%% Implements a web server that sends responses one character
-%% at a time, with random delays between the characters.
-
-start_slow_server(SeqNumServer) ->
- io:format("start slow server when"
- "~n SeqNumServer: ~w"
- "~n", [SeqNumServer]),
- proc_lib:start(
- erlang, apply, [fun() -> init_slow_server(SeqNumServer) end, []]).
-
-init_slow_server(SeqNumServer) ->
- io:format("[webserver ~w] init slow server"
- "~n", [SeqNumServer]),
- {ok, LSock} = gen_tcp:listen(0, [binary, {packet,0}, {active,true},
- {backlog, 100}]),
- io:format("[webserver ~w] LSock: ~p"
- "~n", [SeqNumServer, LSock]),
- {ok, {_IP, Port}} = inet:sockname(LSock),
- io:format("[webserver ~w] Port: ~w"
- "~n", [SeqNumServer, Port]),
- proc_lib:init_ack({ok, self(), Port}),
- loop_slow_server(LSock, SeqNumServer).
-
-loop_slow_server(LSock, SeqNumServer) ->
- io:format("[webserver ~w] entry with"
- "~n LSock: ~p"
- "~n", [SeqNumServer, LSock]),
- Master = self(),
- Acceptor = proc_lib:spawn(
- fun() -> client_handler(Master, LSock, SeqNumServer) end),
- io:format("[webserver ~w] acceptor started"
- "~n Acceptor: ~p"
- "~n", [SeqNumServer, Acceptor]),
- receive
- {accepted, Acceptor} ->
- io:format("[webserver ~w] accepted"
- "~n", [SeqNumServer]),
- loop_slow_server(LSock, SeqNumServer);
- shutdown ->
- gen_tcp:close(LSock),
- exit(Acceptor, kill)
- end.
-
-
-%% Handle one client connection
-client_handler(Master, LSock, SeqNumServer) ->
- io:format("[acceptor ~w] await accept"
- "~n", [SeqNumServer]),
- {ok, CSock} = gen_tcp:accept(LSock),
- io:format("[acceptor ~w] accepted"
- "~n CSock: ~p"
- "~n", [SeqNumServer, CSock]),
- Master ! {accepted, self()},
- set_random_seed(),
- loop_client(1, CSock, SeqNumServer).
+%%-------------------------------------------------------------------------
-loop_client(N, CSock, SeqNumServer) ->
- %% Await request, don't bother parsing it too much,
- %% assuming the entire request arrives in one packet.
- io:format("[acceptor ~w] await request"
- "~n N: ~p"
- "~n", [SeqNumServer, N]),
+remote_socket_close_async(Config) when is_list(Config) ->
+ Request = {url(group_name(Config), "/just_close.html", Config), []},
+ Options = [{sync, false}],
+ Profile = httpc:default_profile(),
+ {ok, RequestId} =
+ httpc:request(get, Request, [], Options, Profile),
receive
- {tcp, CSock, Req} ->
- ReqNum = parse_req_num(Req),
- RespSeqNum = get_next_sequence_number(SeqNumServer),
- Response = f("~s->resp~3..0w/~2..0w", [ReqNum, RespSeqNum, N]),
- Txt = f("Slow server (~p) got ~p, answering with ~p",
- [self(), Req, Response]),
- io:format("~s...~n", [Txt]),
- slowly_send_response(CSock, Response),
- case parse_connection_type(Req) of
- keep_alive ->
- io:format("~s...done~n", [Txt]),
- loop_client(N+1, CSock, SeqNumServer);
- close ->
- io:format("~s...done (closing)~n", [Txt]),
- gen_tcp:close(CSock)
- end
+ {http, {RequestId, {error, socket_closed_remotely}}} ->
+ ok
end.
-slowly_send_response(CSock, Answer) ->
- Response = f("HTTP/1.1 200 OK\r\nContent-Length: ~w\r\n\r\n~s",
- [length(Answer), Answer]),
- lists:foreach(
- fun(Char) ->
- timer:sleep(random:uniform(500)),
- gen_tcp:send(CSock, <<Char>>)
- end,
- Response).
+%%-------------------------------------------------------------------------
-parse_req_num(Request) ->
- Opts = [caseless,{capture,all_but_first,list}],
- {match, [ReqNum]} = re:run(Request, "GET /(.*) HTTP", Opts),
- ReqNum.
+stream_to_pid(Config) when is_list(Config) ->
+ ReceiverPid = create_receiver(pid),
+ Receiver = ReceiverPid,
-parse_connection_type(Request) ->
- Opts = [caseless,{capture,all_but_first,list}],
- {match,[CType]} = re:run(Request, "connection: *(keep-alive|close)", Opts),
- case string:to_lower(CType) of
- "close" -> close;
- "keep-alive" -> keep_alive
- end.
+ stream(ReceiverPid, Receiver, Config),
+ stop_receiver(ReceiverPid).
-set_random_seed() ->
- {_, _, Micros} = now(),
- A = erlang:phash2([make_ref(), self(), Micros]),
- random:seed(A, A, A).
+stream_through_fun(Config) when is_list(Config) ->
+ ReceiverPid = create_receiver(function),
+ Receiver = stream_deliver_fun(ReceiverPid),
-f(F, A) -> lists:flatten(io_lib:format(F,A)).
+ stream(ReceiverPid, Receiver, Config),
+ stop_receiver(ReceiverPid).
+stream_through_mfa(Config) when is_list(Config) ->
+ ReceiverPid = create_receiver(mfa),
+ Receiver = {?MODULE, stream_deliver, [mfa, ReceiverPid]},
+ stream(ReceiverPid, Receiver, Config).
%%-------------------------------------------------------------------------
+inet_opts(Config) when is_list(Config) ->
+ MaxSessions = 5,
+ MaxKeepAlive = 10,
+ KeepAliveTimeout = timer:minutes(2),
+ ConnOptions = [{max_sessions, MaxSessions},
+ {max_keep_alive_length, MaxKeepAlive},
+ {keep_alive_timeout, KeepAliveTimeout}],
+ httpc:set_options(ConnOptions),
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ Timeout = timer:seconds(1),
+ ConnTimeout = Timeout + timer:seconds(1),
+ HttpOptions = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
+ Options0 = [{socket_opts, [{tos, 87},
+ {recbuf, 16#FFFF},
+ {sndbuf, 16#FFFF}]}],
-otp_8106_pid(doc) ->
- ["OTP-8106 - deliver reply info using \"other\" pid"];
-otp_8106_pid(suite) ->
- [];
-otp_8106_pid(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- ReceiverPid = create_receiver(pid),
- Receiver = ReceiverPid,
-
- otp8106(ReceiverPid, Receiver, Config),
+ {ok, {{_,200,_}, [_ | _], ReplyBody0 = [_ | _]}} = httpc:request(get, Request, HttpOptions, Options0),
+ inets_test_lib:check_body(ReplyBody0),
- stop_receiver(ReceiverPid),
-
- ok;
- _ ->
- skip("Failed to start local http-server")
- end.
+ Options1 = [{socket_opts, [{tos, 84},
+ {recbuf, 32#1FFFF},
+ {sndbuf, 32#1FFFF}]}],
+ {ok, {{_,200,_}, [_ | _], ReplyBody1 = [_ | _]}} = httpc:request(get, Request, [], Options1),
+ inets_test_lib:check_body(ReplyBody1).
+%%-------------------------------------------------------------------------
+port_in_host_header(Config) when is_list(Config) ->
-otp_8106_fun(doc) ->
- ["OTP-8106 - deliver reply info using fun"];
-otp_8106_fun(suite) ->
- [];
-otp_8106_fun(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- ReceiverPid = create_receiver(function),
- Receiver = otp_8106_deliver_fun(ReceiverPid),
-
- otp8106(ReceiverPid, Receiver, Config),
+ Request = {url(group_name(Config), "/ensure_host_header_with_port.html", Config), []},
+ {ok, {{_, 200, _}, _, Body}} = httpc:request(get, Request, [], []),
+ inets_test_lib:check_body(Body).
- stop_receiver(ReceiverPid),
-
- ok;
- _ ->
- skip("Failed to start local http-server")
+%%-------------------------------------------------------------------------
+timeout_memory_leak() ->
+ [{doc, "Check OTP-8739"}].
+timeout_memory_leak(Config) when is_list(Config) ->
+ {_DummyServerPid, Port} = otp_8739_dummy_server(),
+ {ok,Host} = inet:gethostname(),
+ Request = {?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ "/dummy.html", []},
+ case httpc:request(get, Request, [{connect_timeout, 500}, {timeout, 1}], [{sync, true}]) of
+ {error, timeout} ->
+ %% And now we check the size of the handler db
+ Info = httpc:info(),
+ ct:print("Info: ~p", [Info]),
+ {value, {handlers, Handlers}} =
+ lists:keysearch(handlers, 1, Info),
+ case Handlers of
+ [] ->
+ ok;
+ _ ->
+ ct:fail({unexpected_handlers, Handlers})
+ end;
+ Unexpected ->
+ ct:fail({unexpected, Unexpected})
end.
+%%--------------------------------------------------------------------
-otp_8106_mfa(doc) ->
- ["OTP-8106 - deliver reply info using mfa callback"];
-otp_8106_mfa(suite) ->
- [];
-otp_8106_mfa(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- ReceiverPid = create_receiver(mfa),
- Receiver = {?MODULE, otp_8106_deliver, [mfa, ReceiverPid]},
-
- otp8106(ReceiverPid, Receiver, Config),
-
- stop_receiver(ReceiverPid),
-
- ok;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
- otp8106(ReceiverPid, Receiver, Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- HTTPOptions = [],
- Options = [{sync, false}, {receiver, Receiver}],
+wait_for_whole_response() ->
+ [{doc, "Check OTP-8154"}].
+wait_for_whole_response(Config) when is_list(Config) ->
- {ok, RequestId} =
- httpc:request(get, Request, HTTPOptions, Options),
+ ReqSeqNumServer = start_sequence_number_server(),
+ RespSeqNumServer = start_sequence_number_server(),
+ {ok, Server, Port} = start_slow_server(RespSeqNumServer),
+ Clients = run_clients(105, Port, ReqSeqNumServer),
+ ok = wait4clients(Clients, timer:minutes(3)),
+ Server ! shutdown,
+ RespSeqNumServer ! shutdown,
+ ReqSeqNumServer ! shutdown.
- Body =
- receive
+%%--------------------------------------------------------------------
+%% Internal Functions ------------------------------------------------
+%%--------------------------------------------------------------------
+stream(ReceiverPid, Receiver, Config) ->
+ Request = {url(group_name(Config), "/dummy.html", Config), []},
+ Options = [{sync, false}, {receiver, Receiver}],
+ {ok, RequestId} =
+ httpc:request(get, Request, [], Options),
+ Body =
+ receive
{reply, ReceiverPid, {RequestId, {{_, 200, _}, _, B}}} ->
B;
{reply, ReceiverPid, Msg} ->
- tsf(Msg);
+ ct:fail(Msg);
{bad_reply, ReceiverPid, Msg} ->
- tsf(Msg)
+ ct:fail(Msg)
end,
- inets_test_lib:check_body(binary_to_list(Body)),
- ok.
-
+ inets_test_lib:check_body(binary_to_list(Body)).
create_receiver(Type) ->
- Parent = self(),
+ Parent = self(),
Receiver = fun() -> receiver(Type, Parent) end,
spawn_link(Receiver).
@@ -3079,8 +983,7 @@ stop_receiver(Pid) ->
receiver(Type, Parent) ->
receive
{stop, Parent} ->
- exit(normal);
-
+ ok;
{http, ReplyInfo} when (Type =:= pid) ->
Parent ! {reply, self(), ReplyInfo},
receiver(Type, Parent);
@@ -3088,266 +991,126 @@ receiver(Type, Parent) ->
{Type, ReplyInfo} ->
Parent ! {reply, self(), ReplyInfo},
receiver(Type, Parent);
-
+
Crap ->
Parent ! {reply, self(), {bad_reply, Crap}},
receiver(Type, Parent)
end.
+stream_deliver_fun(ReceiverPid) ->
+ fun(ReplyInfo) -> stream_deliver(ReplyInfo, function, ReceiverPid) end.
-otp_8106_deliver_fun(ReceiverPid) ->
- fun(ReplyInfo) -> otp_8106_deliver(ReplyInfo, function, ReceiverPid) end.
-
-otp_8106_deliver(ReplyInfo, Type, ReceiverPid) ->
+stream_deliver(ReplyInfo, Type, ReceiverPid) ->
ReceiverPid ! {Type, ReplyInfo},
ok.
+stream_test(Request, To) ->
+ {ok, {{_,200,_}, [_ | _], Body}} =
+ httpc:request(get, Request, [], []),
+ {ok, RequestId} =
+ httpc:request(get, Request, [], [{sync, false}, To]),
+ StreamedBody =
+ receive
+ {http, {RequestId, stream_start, _Headers}} ->
+ receive_streamed_body(RequestId, <<>>);
+ {http, {RequestId, stream_start, _Headers, Pid}} ->
+ receive_streamed_body(RequestId, <<>>, Pid);
+ {http, Msg} ->
+ ct:fail(Msg)
+ end,
-%%-------------------------------------------------------------------------
-
-otp_8056(doc) ->
- "OTP-8056";
-otp_8056(suite) ->
- [];
-otp_8056(Config) when is_list(Config) ->
- Method = get,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- HTTPOptions = [],
- Options1 = [{sync, true}, {stream, {self, once}}],
- Options2 = [{sync, true}, {stream, self}],
- {error, streaming_error} = httpc:request(Method, Request,
- HTTPOptions, Options1),
- tsp("request 1 failed as expected"),
- {error, streaming_error} = httpc:request(Method, Request,
- HTTPOptions, Options2),
- tsp("request 2 failed as expected"),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-otp_8352(doc) ->
- "OTP-8352";
-otp_8352(suite) ->
- [];
-otp_8352(Config) when is_list(Config) ->
- tsp("otp_8352 -> entry with"
- "~n Config: ~p", [Config]),
- case ?config(local_server, Config) of
- ok ->
- tsp("local-server running"),
-
- tsp("initial profile info(1): ~p", [httpc:info()]),
-
- MaxSessions = 5,
- MaxKeepAlive = 10,
- KeepAliveTimeout = timer:minutes(2),
- ConnOptions = [{max_sessions, MaxSessions},
- {max_keep_alive_length, MaxKeepAlive},
- {keep_alive_timeout, KeepAliveTimeout}],
- httpc:set_options(ConnOptions),
-
- Method = get,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- Timeout = timer:seconds(1),
- ConnTimeout = Timeout + timer:seconds(1),
- HttpOptions1 = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
- Options1 = [{socket_opts, [{tos, 87},
- {recbuf, 16#FFFF},
- {sndbuf, 16#FFFF}]}],
- case httpc:request(Method, Request, HttpOptions1, Options1) of
- {ok, {{_,200,_}, [_ | _], ReplyBody1 = [_ | _]}} ->
- %% equivaliant to httpc:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(ReplyBody1);
- {ok, UnexpectedReply1} ->
- tsf({unexpected_reply, UnexpectedReply1});
- {error, _} = Error1 ->
- tsf({bad_reply, Error1})
- end,
-
- tsp("profile info (2): ~p", [httpc:info()]),
-
- HttpOptions2 = [],
- Options2 = [{socket_opts, [{tos, 84},
- {recbuf, 32#1FFFF},
- {sndbuf, 32#1FFFF}]}],
- case httpc:request(Method, Request, HttpOptions2, Options2) of
- {ok, {{_,200,_}, [_ | _], ReplyBody2 = [_ | _]}} ->
- %% equivaliant to httpc:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(ReplyBody2);
- {ok, UnexpectedReply2} ->
- tsf({unexpected_reply, UnexpectedReply2});
- {error, _} = Error2 ->
- tsf({bad_reply, Error2})
- end,
- tsp("profile info (3): ~p", [httpc:info()]),
- ok;
-
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-
-otp_8371(doc) ->
- ["OTP-8371"];
-otp_8371(suite) ->
- [];
-otp_8371(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++
- "/ensure_host_header_with_port.html",
-
- case httpc:request(get, {URL, []}, [], []) of
- {ok, Result} ->
- case Result of
- {{_, 200, _}, _Headers, Body} ->
- tsp("expected response with"
- "~n Body: ~p", [Body]),
- ok;
- {StatusLine, Headers, Body} ->
- tsp("expected response with"
- "~n StatusLine: ~p"
- "~n Headers: ~p"
- "~n Body: ~p", [StatusLine, Headers, Body]),
- tsf({unexpected_result,
- [{status_line, StatusLine},
- {headers, Headers},
- {body, Body}]});
- _ ->
- tsf({unexpected_result, Result})
- end;
- Error ->
- tsf({request_failed, Error})
- end,
+ Body == binary_to_list(StreamedBody).
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipv6, enabled}]),
+url(http, End, Config) ->
+ Port = ?config(port, Config),
+ {ok,Host} = inet:gethostname(),
+ ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
+url(https, End, Config) ->
+ Port = ?config(port, Config),
+ {ok,Host} = inet:gethostname(),
+ ?TLS_URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End;
+url(sim_http, End, Config) ->
+ url(http, End, Config);
+url(sim_https, End, Config) ->
+ url(https, End, Config).
+url(http, UserInfo, End, Config) ->
+ Port = ?config(port, Config),
+ ?URL_START ++ UserInfo ++ integer_to_list(Port) ++ End;
+url(https, UserInfo, End, Config) ->
+ Port = ?config(port, Config),
+ ?TLS_URL_START ++ UserInfo ++ integer_to_list(Port) ++ End;
+url(sim_http, UserInfo, End, Config) ->
+ url(http, UserInfo, End, Config);
+url(sim_https, UserInfo, End, Config) ->
+ url(https, UserInfo, End, Config).
+
+group_name(Config) ->
+ GroupProp = ?config(tc_group_properties, Config),
+ proplists:get_value(name, GroupProp).
+
+server_start(sim_http, _) ->
+ Inet = inet_version(),
+ ok = httpc:set_options([{ipfamily, Inet}]),
+ {_Pid, Port} = dummy_server(Inet),
+ Port;
+
+server_start(sim_https, SslConfig) ->
+ Inet = inet_version(),
+ ok = httpc:set_options([{ipfamily, Inet}]),
+ {_Pid, Port} = dummy_server(ssl, Inet, SslConfig),
+ Port;
+
+server_start(_, HttpdConfig) ->
+ {ok, Pid} = inets:start(httpd, HttpdConfig),
+ Serv = inets:services_info(),
+ {value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
+ proplists:get_value(port, Info).
+
+server_config(http, Config) ->
+ ServerRoot = ?config(server_root, Config),
+ [{port, 0},
+ {server_name,"httpc_test"},
+ {server_root, ServerRoot},
+ {document_root, ?config(doc_root, Config)},
+ {bind_address, any},
+ {ipfamily, inet_version()},
+ {mime_type, "text/plain"},
+ {script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}}
+ ];
+
+server_config(https, Config) ->
+ [{socket_type, {essl, ssl_config(Config)}} | server_config(http, Config)];
+server_config(sim_https, Config) ->
+ ssl_config(Config);
+server_config(_, _) ->
+ [].
+
+start_apps(https) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(sim_https) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(_) ->
ok.
-
-%%-------------------------------------------------------------------------
-
-otp_8739(doc) ->
- ["OTP-8739"];
-otp_8739(suite) ->
- [];
-otp_8739(Config) when is_list(Config) ->
- {_DummyServerPid, Port} = otp_8739_dummy_server(),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Method = get,
- Request = {URL, []},
- HttpOptions = [{connect_timeout, 500}, {timeout, 1}],
- Options = [{sync, true}],
- case httpc:request(Method, Request, HttpOptions, Options) of
- {error, timeout} ->
- %% And now we check the size of the handler db
- Info = httpc:info(),
- tsp("Info: ~p", [Info]),
- {value, {handlers, Handlers}} =
- lists:keysearch(handlers, 1, Info),
- case Handlers of
- [] ->
- ok;
- _ ->
- tsf({unexpected_handlers, Handlers})
- end;
- Unexpected ->
- tsf({unexpected, Unexpected})
- end.
-
-
-otp_8739_dummy_server() ->
- Parent = self(),
- Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end),
- receive
- {port, Port} ->
- {Pid, Port}
- end.
-
-otp_8739_dummy_server_init(Parent) ->
- {ok, ListenSocket} =
- gen_tcp:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}]),
- {ok, Port} = inet:port(ListenSocket),
- Parent ! {port, Port},
- otp_8739_dummy_server_main(Parent, ListenSocket).
-
-otp_8739_dummy_server_main(_Parent, ListenSocket) ->
- case gen_tcp:accept(ListenSocket) of
- {ok, Sock} ->
- %% Ignore the request, and simply wait for the socket to close
- receive
- {tcp_closed, Sock} ->
- (catch gen_tcp:close(ListenSocket)),
- exit(normal);
- {tcp_error, Sock, Reason} ->
- tsp("socket error: ~p", [Reason]),
- (catch gen_tcp:close(ListenSocket)),
- exit(normal)
- after 10000 ->
- %% Just in case
- (catch gen_tcp:close(Sock)),
- (catch gen_tcp:close(ListenSocket)),
- exit(timeout)
- end;
- Error ->
- exit(Error)
- end.
-
-
-%%-------------------------------------------------------------------------
-
-initial_server_connect(doc) ->
- ["If this test cases times out the init of httpc_handler process is"
- "blocking the manager/client process (implementation dependent which) but nither"
- "should be blocked."];
-initial_server_connect(suite) ->
- [];
-initial_server_connect(Config) when is_list(Config) ->
+ssl_config(Config) ->
DataDir = ?config(data_dir, Config),
- ok = httpc:set_options([{ipfamily, inet}]),
-
- CertFile = filename:join(DataDir, "ssl_server_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
-
- {DummyServerPid, Port} = dummy_ssl_server_hang(self(), ipv4, SSLOptions),
-
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/index.html",
-
- httpc:request(get, {URL, []}, [{ssl,{essl,[]}}], [{sync, false}]),
-
- [{session_cookies,[]}] = httpc:which_cookies(),
+ [{certfile, filename:join(DataDir, "ssl_server_cert.pem")},
+ {verify, verify_none}
+ ].
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]).
-
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
- ConfDir = filename:join(ServerRoot, "conf"),
+setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
CgiDir = filename:join(ServerRoot, "cgi-bin"),
ok = file:make_dir(ServerRoot),
ok = file:make_dir(DocRoot),
- ok = file:make_dir(ConfDir),
ok = file:make_dir(CgiDir),
{ok, Files} = file:list_dir(DataDir),
lists:foreach(fun(File) -> case lists:suffix(".html", File) of
true ->
- inets_test_lib:copy_file(File,
- DataDir,
+ inets_test_lib:copy_file(File,
+ DataDir,
DocRoot);
false ->
ok
@@ -3362,86 +1125,41 @@ setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
end,
inets_test_lib:copy_file(Cgi, DataDir, CgiDir),
- inets_test_lib:copy_file("mime.types", DataDir, ConfDir).
-
-create_config(FileName, ComType, Port, PrivDir, ServerRoot, DocRoot,
- SSLDir) ->
- MaxHdrSz = io_lib:format("~p", [256]),
- MaxHdrAct = io_lib:format("~p", [close]),
- SSL =
- case ComType of
- ssl ->
- [cline(["SSLCertificateFile ",
- filename:join(SSLDir, "ssl_server_cert.pem")]),
- cline(["SSLCertificateKeyFile ",
- filename:join(SSLDir, "ssl_server_cert.pem")]),
- cline(["SSLVerifyClient 0"])];
- _ ->
- []
- end,
+ AbsCgi = filename:join([CgiDir, Cgi]),
+ {ok, FileInfo} = file:read_file_info(AbsCgi),
+ ok = file:write_file_info(AbsCgi, FileInfo#file_info{mode = 8#00755}).
- Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
- " mod_include mod_dir mod_get mod_head"
- " mod_log mod_disk_log mod_trace",
-
- %% BindAddress = "*|inet", % Force the use of IPv4
- BindAddress = "*", % This corresponds to using IpFamily inet6fb4
-
- HttpConfig = [
- cline(["BindAddress ", BindAddress]),
- cline(["Port ", integer_to_list(Port)]),
- cline(["ServerName ", "httpc_test"]),
- cline(["SocketType ", atom_to_list(ComType)]),
- cline([Mod_order]),
- cline(["ServerRoot ", ServerRoot]),
- cline(["DocumentRoot ", DocRoot]),
- cline(["MaxHeaderSize ",MaxHdrSz]),
- cline(["MaxHeaderAction ",MaxHdrAct]),
- cline(["DirectoryIndex ", "index.html "]),
- cline(["DefaultType ", "text/plain"]),
- cline(["ScriptAlias /cgi-bin/ ",
- filename:join(ServerRoot, "cgi-bin"), "/"]),
- SSL],
- ConfigFile = filename:join([PrivDir,FileName]),
- {ok, Fd} = file:open(ConfigFile, [write]),
- ok = file:write(Fd, lists:flatten(HttpConfig)),
- ok = file:close(Fd).
-
-cline(List) ->
- lists:flatten([List, "\r\n"]).
-
-is_proxy_available(Proxy, Port) ->
- case gen_tcp:connect(Proxy, Port, []) of
- {ok, Socket} ->
- gen_tcp:close(Socket),
- true;
- _ ->
- false
- end.
-receive_streamed_body(RequestId, Body) ->
- receive
- {http, {RequestId, stream, BinBodyPart}} ->
- receive_streamed_body(RequestId,
- <<Body/binary, BinBodyPart/binary>>);
- {http, {RequestId, stream_end, _Headers}} ->
- Body;
- {http, Msg} ->
- tsf(Msg)
- end.
+keep_alive_requests(Request, Profile) ->
+ {ok, RequestIdA0} =
+ httpc:request(get, Request, [], [{sync, false}], Profile),
+ {ok, RequestIdA1} =
+ httpc:request(get, Request, [], [{sync, false}], Profile),
+ {ok, RequestIdA2} =
+ httpc:request(get, Request, [], [{sync, false}], Profile),
-receive_streamed_body(RequestId, Body, Pid) ->
- httpc:stream_next(Pid),
- test_server:format("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
- receive
- {http, {RequestId, stream, BinBodyPart}} ->
- receive_streamed_body(RequestId,
- <<Body/binary, BinBodyPart/binary>>,
- Pid);
- {http, {RequestId, stream_end, _Headers}} ->
- Body;
- {http, Msg} ->
- tsf(Msg)
+ receive_replys([RequestIdA0, RequestIdA1, RequestIdA2]),
+
+ {ok, RequestIdB0} =
+ httpc:request(get, Request, [], [{sync, false}], Profile),
+ {ok, RequestIdB1} =
+ httpc:request(get, Request, [], [{sync, false}], Profile),
+ {ok, RequestIdB2} =
+ httpc:request(get, Request, [], [{sync, false}], Profile),
+
+ ok = httpc:cancel_request(RequestIdB1, Profile),
+ ct:print("Cancel ~p~n", [RequestIdB1]),
+ receive_replys([RequestIdB0, RequestIdB2]).
+
+
+receive_replys([]) ->
+ ok;
+receive_replys([ID|IDs]) ->
+ receive
+ {http, {ID, {{_, 200, _}, [_|_], _}}} ->
+ receive_replys(IDs);
+ {http, {Other, {{_, 200, _}, [_|_], _}}} ->
+ ct:pal({recived_canceld_id, Other})
end.
%% Perform a synchronous stop
@@ -3452,55 +1170,46 @@ dummy_server_stop(Pid) ->
ok
end.
-dummy_server(IpV) ->
- dummy_server(self(), ip_comm, IpV, []).
+inet_version() ->
+ inet. %% Just run inet for now
+ %% case gen_tcp:listen(0,[inet6]) of
+ %% {ok, S} ->
+ %% gen_tcp:close(S),
+ %% inet6;
+ %% _ ->
+ %% inet
+ %%end.
+
+dummy_server(Inet) ->
+ dummy_server(self(), ip_comm, Inet, []).
-dummy_server(SocketType, IpV, Extra) ->
- dummy_server(self(), SocketType, IpV, Extra).
+dummy_server(SocketType, Inet, Extra) ->
+ dummy_server(self(), SocketType, Inet, Extra).
-dummy_server(Caller, SocketType, IpV, Extra) ->
- Args = [Caller, SocketType, IpV, Extra],
+dummy_server(Caller, SocketType, Inet, Extra) ->
+ Args = [Caller, SocketType, Inet, Extra],
Pid = spawn(httpc_SUITE, dummy_server_init, Args),
receive
{port, Port} ->
{Pid, Port}
end.
-dummy_server_init(Caller, ip_comm, IpV, _) ->
+dummy_server_init(Caller, ip_comm, Inet, _) ->
BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}],
- {ok, ListenSocket} =
- case IpV of
- ipv4 ->
- tsp("ip_comm ipv4 listen", []),
- gen_tcp:listen(0, [inet | BaseOpts]);
- ipv6 ->
- tsp("ip_comm ipv6 listen", []),
- gen_tcp:listen(0, [inet6 | BaseOpts])
- end,
+ {ok, ListenSocket} = gen_tcp:listen(0, [Inet | BaseOpts]),
{ok, Port} = inet:port(ListenSocket),
- tsp("dummy_server_init(ip_comm) -> Port: ~p", [Port]),
Caller ! {port, Port},
dummy_ipcomm_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
[], ListenSocket);
-dummy_server_init(Caller, essl, IpV, SSLOptions) ->
- BaseOpts = [{ssl_imp, new},
- {backlog, 128}, binary, {reuseaddr,true}, {active, false} |
+
+dummy_server_init(Caller, ssl, Inet, SSLOptions) ->
+ BaseOpts = [binary, {reuseaddr,true}, {active, false} |
SSLOptions],
- dummy_ssl_server_init(Caller, BaseOpts, IpV).
-
-dummy_ssl_server_init(Caller, BaseOpts, IpV) ->
- {ok, ListenSocket} =
- case IpV of
- ipv4 ->
- tsp("dummy_ssl_server_init -> ssl ipv4 listen", []),
- ssl:listen(0, [inet | BaseOpts]);
- ipv6 ->
- tsp("dummy_ssl_server_init -> ssl ipv6 listen", []),
- ssl:listen(0, [inet6 | BaseOpts])
- end,
- tsp("dummy_ssl_server_init -> ListenSocket: ~p", [ListenSocket]),
+ dummy_ssl_server_init(Caller, BaseOpts, Inet).
+
+dummy_ssl_server_init(Caller, BaseOpts, Inet) ->
+ {ok, ListenSocket} = ssl:listen(0, [Inet | BaseOpts]),
{ok, {_, Port}} = ssl:sockname(ListenSocket),
- tsp("dummy_ssl_server_init -> Port: ~p", [Port]),
Caller ! {port, Port},
dummy_ssl_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
[], ListenSocket).
@@ -3508,85 +1217,56 @@ dummy_ssl_server_init(Caller, BaseOpts, IpV) ->
dummy_ipcomm_server_loop(MFA, Handlers, ListenSocket) ->
receive
stop ->
- tsp("dummy_ipcomm_server_loop -> stop handlers", []),
lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
{stop, From} ->
- tsp("dummy_ipcomm_server_loop -> "
- "stop command from ~p for handlers (~p)", [From, Handlers]),
Stopper = fun(Handler) -> Handler ! stop end,
lists:foreach(Stopper, Handlers),
From ! {stopped, self()}
after 0 ->
- tsp("dummy_ipcomm_server_loop -> await accept", []),
{ok, Socket} = gen_tcp:accept(ListenSocket),
- tsp("dummy_ipcomm_server_loop -> accepted: ~p", [Socket]),
HandlerPid = dummy_request_handler(MFA, Socket),
- tsp("dummy_icomm_server_loop -> handler created: ~p", [HandlerPid]),
gen_tcp:controlling_process(Socket, HandlerPid),
- tsp("dummy_ipcomm_server_loop -> "
- "control transfered to handler", []),
HandlerPid ! ipcomm_controller,
- tsp("dummy_ipcomm_server_loop -> "
- "handler informed about control transfer", []),
dummy_ipcomm_server_loop(MFA, [HandlerPid | Handlers],
- ListenSocket)
+ ListenSocket)
end.
dummy_ssl_server_loop(MFA, Handlers, ListenSocket) ->
receive
stop ->
- tsp("dummy_ssl_server_loop -> stop handlers", []),
lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
{stop, From} ->
- tsp("dummy_ssl_server_loop -> "
- "stop command from ~p for handlers (~p)", [From, Handlers]),
Stopper = fun(Handler) -> Handler ! stop end,
lists:foreach(Stopper, Handlers),
From ! {stopped, self()}
after 0 ->
- tsp("dummy_ssl_server_loop -> await accept", []),
{ok, Socket} = ssl:transport_accept(ListenSocket),
- tsp("dummy_ssl_server_loop -> accepted: ~p", [Socket]),
HandlerPid = dummy_request_handler(MFA, Socket),
- tsp("dummy_ssl_server_loop -> handler created: ~p", [HandlerPid]),
ssl:controlling_process(Socket, HandlerPid),
- tsp("dummy_ssl_server_loop -> control transfered to handler", []),
HandlerPid ! ssl_controller,
- tsp("dummy_ssl_server_loop -> "
- "handler informed about control transfer", []),
dummy_ssl_server_loop(MFA, [HandlerPid | Handlers],
ListenSocket)
end.
dummy_request_handler(MFA, Socket) ->
- tsp("spawn request handler", []),
spawn(httpc_SUITE, dummy_request_handler_init, [MFA, Socket]).
dummy_request_handler_init(MFA, Socket) ->
SockType =
receive
ipcomm_controller ->
- tsp("dummy_request_handler_init -> "
- "received ip_comm controller - activate", []),
inet:setopts(Socket, [{active, true}]),
ip_comm;
ssl_controller ->
- tsp("dummy_request_handler_init -> "
- "received ssl controller - activate", []),
ssl:setopts(Socket, [{active, true}]),
ssl
end,
dummy_request_handler_loop(MFA, SockType, Socket).
dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
- tsp("dummy_request_handler_loop -> entry with"
- "~n Module: ~p"
- "~n Function: ~p"
- "~n Args: ~p", [Module, Function, Args]),
receive
{Proto, _, Data} when (Proto =:= tcp) orelse (Proto =:= ssl) ->
- tsp("dummy_request_handler_loop -> [~w] Data ~p", [Proto, Data]),
- case handle_request(Module, Function, [Data | Args], Socket, Proto) of
+ case handle_request(Module, Function, [Data | Args], Socket) of
stop when Proto =:= tcp ->
gen_tcp:close(Socket);
stop when Proto =:= ssl ->
@@ -3600,49 +1280,26 @@ dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
ssl:close(Socket)
end.
-
-mk_close(tcp) -> fun(Sock) -> gen_tcp:close(Sock) end;
-mk_close(ssl) -> fun(Sock) -> ssl:close(Sock) end.
-
-mk_send(tcp) -> fun(Sock, Data) -> gen_tcp:send(Sock, Data) end;
-mk_send(ssl) -> fun(Sock, Data) -> ssl:send(Sock, Data) end.
-
-handle_request(Module, Function, Args, Socket, Proto) ->
- Close = mk_close(Proto),
- Send = mk_send(Proto),
- handle_request(Module, Function, Args, Socket, Close, Send).
-
-handle_request(Module, Function, Args, Socket, Close, Send) ->
- tsp("handle_request -> entry with"
- "~n Module: ~p"
- "~n Function: ~p"
- "~n Args: ~p", [Module, Function, Args]),
+handle_request(Module, Function, Args, Socket) ->
case Module:Function(Args) of
{ok, Result} ->
- tsp("handle_request -> ok"
- "~n Result: ~p", [Result]),
- case (catch handle_http_msg(Result, Socket, Close, Send)) of
+ case handle_http_msg(Result, Socket) of
stop ->
stop;
<<>> ->
- tsp("handle_request -> empty data"),
{httpd_request, parse, [[<<>>, ?HTTP_MAX_HEADER_SIZE]]};
Data ->
handle_request(httpd_request, parse,
- [Data |[?HTTP_MAX_HEADER_SIZE]], Socket,
- Close, Send)
+ [Data |[?HTTP_MAX_HEADER_SIZE]], Socket)
end;
NewMFA ->
- tsp("handle_request -> "
- "~n NewMFA: ~p", [NewMFA]),
NewMFA
end.
-handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket, Close, Send) ->
- tsp("handle_http_msg -> entry with: "
- "~n RelUri: ~p"
- "~n Headers: ~p"
- "~n Body: ~p", [RelUri, Headers, Body]),
+handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket) ->
+
+ ct:print("Request: ~p ~p", [Method, RelUri]),
+
NextRequest =
case RelUri of
"/dummy_headers.html" ->
@@ -3663,217 +1320,69 @@ handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket, Close, Send) ->
end
end,
- tsp("handle_http_msg -> NextRequest: ~p", [NextRequest]),
case (catch ets:lookup(cookie, cookies)) of
[{cookies, true}]->
- tsp("handle_http_msg -> check cookies ~p", []),
check_cookie(Headers);
_ ->
ok
end,
-
+
+ {ok, {_, Port}} = sockname(Socket),
+
+
DefaultResponse = "HTTP/1.1 200 ok\r\n" ++
"Content-Length:32\r\n\r\n"
"<HTML><BODY>foobar</BODY></HTML>",
- Msg =
- case RelUri of
- "/just_close.html" ->
- close;
- "/no_content.html" ->
- "HTTP/1.0 204 No Content\r\n\r\n";
- "/no_headers.html" ->
- "HTTP/1.0 200 OK\r\n\r\nTEST";
- "/ensure_host_header_with_port.html" ->
- %% tsp("handle_http_msg -> validate host with port"),
- case ensure_host_header_with_port(Headers) of
- true ->
- B =
- "<HTML><BODY>" ++
- "host with port" ++
- "</BODY></HTML>",
- Len = integer_to_list(length(B)),
- "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B;
- false ->
- B =
- "<HTML><BODY>" ++
- "Internal Server Error - host without port" ++
- "</BODY></HTML>",
- Len = integer_to_list(length(B)),
- "HTTP/1.1 500 Internal Server Error\r\n" ++
- "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
- end;
- "/300.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 300 Multiple Choices\r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:0\r\n\r\n";
- "/301.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 301 Moved Permanently\r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/302.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 302 Found \r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/307.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 307 Temporary Rediect \r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/500.html" ->
- "HTTP/1.1 500 Internal Server Error\r\n" ++
- "Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY></HTML>";
- "/503.html" ->
- case ets:lookup(unavailable, 503) of
- [{503, unavailable}] ->
- ets:insert(unavailable, {503, available}),
- "HTTP/1.1 503 Service Unavailable\r\n" ++
- "Retry-After:5\r\n" ++
- "Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY></HTML>";
- [{503, available}] ->
- DefaultResponse;
- [{503, long_unavailable}] ->
- "HTTP/1.1 503 Service Unavailable\r\n" ++
- "Retry-After:120\r\n" ++
- "Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY></HTML>"
- end;
- "/redirectloop.html" -> %% Create a potential endless loop!
- {ok, Port} = inet:port(Socket),
- NewUri = ?URL_START ++
- integer_to_list(Port) ++ "/redirectloop.html",
- "HTTP/1.1 300 Multiple Choices\r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:0\r\n\r\n";
- "/userinfo.html" ->
- Challange = "HTTP/1.1 401 Unauthorized \r\n" ++
- "WWW-Authenticate:Basic" ++"\r\n" ++
- "Content-Length:0\r\n\r\n",
- case auth_header(Headers) of
- {ok, Value} ->
- handle_auth(Value, Challange, DefaultResponse);
- _ ->
- Challange
- end;
- "/dummy_headers.html" ->
- %% The client will only care about the Transfer-Encoding
- %% header the rest of these headers are left to the
- %% user to evaluate. This is not a valid response
- %% it only tests that the header handling code works.
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n" ++
- "Pragma:1#no-cache\r\n" ++
- "Via:1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" ++
- "Warning:1#pseudonym foobar\r\n" ++
- "Vary:*\r\n" ++
- "Trailer:Other:inets_test\r\n" ++
- "Upgrade:HTTP/2.0\r\n" ++
- "Age:4711\r\n" ++
- "Transfer-Encoding:chunked\r\n" ++
- "Content-Encoding:foo\r\n" ++
- "Content-Language:en\r\n" ++
- "Content-Location:http://www.foobar.se\r\n" ++
- "Content-MD5:104528739076276072743283077410617235478\r\n"
- ++
- "Content-Range:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
- "Expires:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
- "Proxy-Authenticate:#1Basic" ++
- "\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
- http_chunk:encode_last();
- "/capital_transfer_encoding.html" ->
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Transfer-Encoding:Chunked\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
- http_chunk:encode_last();
- "/cookie.html" ->
- "HTTP/1.1 200 ok\r\n" ++
- "set-cookie:" ++ "test_cookie=true; path=/;" ++
- "max-age=60000\r\n" ++
- "Content-Length:32\r\n\r\n"++
- "<HTML><BODY>foobar</BODY></HTML>";
- "/missing_crlf.html" ->
- "HTTP/1.1 200 ok" ++
- "Content-Length:32\r\n" ++
- "<HTML><BODY>foobar</BODY></HTML>";
- "/wrong_statusline.html" ->
- "ok 200 HTTP/1.1\r\n\r\n" ++
- "Content-Length:32\r\n\r\n" ++
- "<HTML><BODY>foobar</BODY></HTML>";
- "/once_chunked.html" ->
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Transfer-Encoding:Chunked\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- Send(Socket,
- http_chunk:encode("obar</BODY></HTML>")),
- http_chunk:encode_last();
- "/once.html" ->
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, "<HTML><BODY>fo"),
- test_server:sleep(1000),
- Send(Socket, "ob"),
- test_server:sleep(1000),
- Send(Socket, "ar</BODY></HTML>");
- "/invalid_http.html" ->
- "HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
- "Transfer-Encoding:chunked\r\n\r\n";
- "/missing_reason_phrase.html" ->
- "HTTP/1.1 200\r\n" ++
- "Content-Length: 32\r\n\r\n"
- "<HTML><BODY>foobar</BODY></HTML>";
- "/missing_CR.html" ->
- "HTTP/1.1 200 ok\n" ++
- "Content-Length:32\r\n\n"
- "<HTML><BODY>foobar</BODY></HTML>";
- _ ->
- DefaultResponse
- end,
-
- tsp("handle_http_msg -> Msg: ~p", [Msg]),
+ Msg = handle_uri(Method,RelUri, Port, Headers, Socket, DefaultResponse),
+
case Msg of
ok ->
- %% Previously, this resulted in an {error, einval}. Now what?
ok;
close ->
%% Nothing to send, just close
- Close(Socket);
+ close(Socket);
_ when is_list(Msg) orelse is_binary(Msg) ->
- Send(Socket, Msg)
+ case Msg of
+ [] ->
+ ct:print("Empty Msg", []);
+ _ ->
+ ct:print("Response: ~p", [Msg]),
+ send(Socket, Msg)
+ end
end,
- tsp("handle_http_msg -> done"),
NextRequest.
+dummy_ssl_server_hang(Caller, Inet, SslOpt) ->
+ Pid = spawn(httpc_SUITE, dummy_ssl_server_hang_init, [Caller, Inet, SslOpt]),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+dummy_ssl_server_hang_init(Caller, Inet, SslOpt) ->
+ {ok, ListenSocket} =
+ ssl:listen(0, [binary, Inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}] ++ SslOpt),
+ {ok, {_,Port}} = ssl:sockname(ListenSocket),
+ Caller ! {port, Port},
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
+ dummy_ssl_server_hang_loop(AcceptSocket).
+
+dummy_ssl_server_hang_loop(_) ->
+ %% Do not do ssl:ssl_accept as we
+ %% want to time out the underlying gen_tcp:connect
+ receive
+ stop ->
+ ok
+ end.
+
ensure_host_header_with_port([]) ->
false;
ensure_host_header_with_port(["host: " ++ Host| _]) ->
case string:tokens(Host, [$:]) of
- [ActualHost, Port] ->
- tsp("ensure_host_header_with_port -> "
- "~n ActualHost: ~p"
- "~n Port: ~p", [ActualHost, Port]),
+ [_ActualHost, _Port] ->
true;
_ ->
false
@@ -3891,15 +1400,15 @@ auth_header([_ | Tail]) ->
handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
case string:tokens(base64:decode_to_string(UserInfo), ":") of
["alladin", "sesame"] = Auth ->
- test_server:format("Auth: ~p~n", [Auth]),
+ ct:print("Auth: ~p~n", [Auth]),
DefaultResponse;
Other ->
- test_server:format("UnAuth: ~p~n", [Other]),
+ ct:print("UnAuth: ~p~n", [Other]),
Challange
end.
check_cookie([]) ->
- tsf(no_cookie_header);
+ ct:fail(no_cookie_header);
check_cookie(["cookie:" ++ _Value | _]) ->
ok;
check_cookie([_Head | Tail]) ->
@@ -3912,122 +1421,541 @@ content_length(["content-length:" ++ Value | _]) ->
content_length([_Head | Tail]) ->
content_length(Tail).
-provocate_not_modified_bug(Url) ->
- Timeout = 15000, %% 15s should be plenty
+handle_uri(_,"/just_close.html",_,_,_,_) ->
+ close;
+handle_uri(_,"/no_content.html",_,_,_,_) ->
+ "HTTP/1.0 204 No Content\r\n\r\n";
+
+handle_uri(_,"/no_headers.html",_,_,_,_) ->
+ "HTTP/1.0 200 OK\r\n\r\nTEST";
+
+handle_uri("TRACE","/trace.html",_,_,_,_) ->
+ Body = "TRACE /trace.html simulate HTTP TRACE ",
+ "HTTP/1.1 200 OK\r\n" ++ "Content-Length:" ++ integer_to_list(length(Body)) ++ "\r\n\r\n" ++ Body;
+
+handle_uri(_,"/ensure_host_header_with_port.html",_,Headers,_,_) ->
+ case ensure_host_header_with_port(Headers) of
+ true ->
+ B =
+ "<HTML><BODY>" ++
+ "host with port" ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B;
+ false ->
+ B =
+ "<HTML><BODY>" ++
+ "Internal Server Error - host without port" ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
+ end;
- {ok, {{_, 200, _}, ReplyHeaders, _Body}} =
- httpc:request(get, {Url, []}, [{timeout, Timeout}], []),
- Etag = pick_header(ReplyHeaders, "ETag"),
- Last = pick_header(ReplyHeaders, "last-modified"),
-
- case httpc:request(get, {Url, [{"If-None-Match", Etag},
- {"If-Modified-Since", Last}]},
- [{timeout, 15000}],
- []) of
- {ok, {{_, 304, _}, _, _}} -> %% The expected reply
- page_unchanged;
- {ok, {{_, 200, _}, _, _}} ->
- %% If the page has changed since the
- %% last request we retry to
- %% trigger the bug
- provocate_not_modified_bug(Url);
- {error, timeout} ->
- %% Not what we expected. Tcpdump can be used to
- %% verify that we receive the complete http-reply
- %% but still time out.
- incorrect_result
+handle_uri(_,"/300.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 300 Multiple Choices\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
+handle_uri("HEAD","/301.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/301.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
+handle_uri("HEAD","/302.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ "HTTP/1.1 302 Found \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/302.html",Port, _,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 302 Found \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
+handle_uri("HEAD","/303.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ "HTTP/1.1 302 See Other \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+handle_uri(_,"/303.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 303 See Other \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+handle_uri("HEAD","/307.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ "HTTP/1.1 307 Temporary Rediect \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+handle_uri(_,"/307.html",Port,_,Socket,_) ->
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/dummy.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 307 Temporary Rediect \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
+handle_uri(_,"/500.html",_,_,_,_) ->
+ "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:47\r\n\r\n" ++
+ "<HTML><BODY>Internal Server Error</BODY></HTML>";
+
+handle_uri(_,"/503.html",_,_,_,DefaultResponse) ->
+ case ets:lookup(unavailable, 503) of
+ [{503, unavailable}] ->
+ ets:insert(unavailable, {503, available}),
+ "HTTP/1.1 503 Service Unavailable\r\n" ++
+ "Retry-After:5\r\n" ++
+ "Content-Length:47\r\n\r\n" ++
+ "<HTML><BODY>Internal Server Error</BODY></HTML>";
+ [{503, available}] ->
+ DefaultResponse;
+ [{503, long_unavailable}] ->
+ "HTTP/1.1 503 Service Unavailable\r\n" ++
+ "Retry-After:120\r\n" ++
+ "Content-Length:47\r\n\r\n" ++
+ "<HTML><BODY>Internal Server Error</BODY></HTML>"
+ end;
+
+handle_uri(_,"/redirectloop.html",Port,_,Socket,_) ->
+ %% Create a potential endless loop!
+ NewUri = url_start(Socket) ++
+ integer_to_list(Port) ++ "/redirectloop.html",
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 300 Multiple Choices\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
+
+handle_uri(_,"/userinfo.html", _,Headers,_, DefaultResponse) ->
+ Challange = "HTTP/1.1 401 Unauthorized \r\n" ++
+ "WWW-Authenticate:Basic" ++"\r\n" ++
+ "Content-Length:0\r\n\r\n",
+ case auth_header(Headers) of
+ {ok, Value} ->
+ handle_auth(Value, Challange, DefaultResponse);
+ _ ->
+ Challange
+ end;
+
+handle_uri(_,"/dummy_headers.html",_,_,Socket,_) ->
+ %% The client will only care about the Transfer-Encoding
+ %% header the rest of these headers are left to the
+ %% user to evaluate. This is not a valid response
+ %% it only tests that the header handling code works.
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:32\r\n" ++
+ "Pragma:1#no-cache\r\n" ++
+ "Via:1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" ++
+ "Warning:1#pseudonym foobar\r\n" ++
+ "Vary:*\r\n" ++
+ "Trailer:Other:inets_test\r\n" ++
+ "Upgrade:HTTP/2.0\r\n" ++
+ "Age:4711\r\n" ++
+ "Transfer-Encoding:chunked\r\n" ++
+ "Content-Encoding:foo\r\n" ++
+ "Content-Language:en\r\n" ++
+ "Content-Location:http://www.foobar.se\r\n" ++
+ "Content-MD5:104528739076276072743283077410617235478\r\n"
+ ++
+ "Content-Range:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
+ "Expires:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
+ "Proxy-Authenticate:#1Basic" ++
+ "\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+
+handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+
+handle_uri(_,"/cookie.html",_,_,_,_) ->
+ "HTTP/1.1 200 ok\r\n" ++
+ "set-cookie:" ++ "test_cookie=true; path=/;" ++
+ "max-age=60000\r\n" ++
+ "Content-Length:32\r\n\r\n"++
+ "<HTML><BODY>foobar</BODY></HTML>";
+
+handle_uri(_,"/missing_crlf.html",_,_,_,_) ->
+ "HTTP/1.1 200 ok" ++
+ "Content-Length:32\r\n" ++
+ "<HTML><BODY>foobar</BODY></HTML>";
+
+handle_uri(_,"/wrong_statusline.html",_,_,_,_) ->
+ "ok 200 HTTP/1.1\r\n\r\n" ++
+ "Content-Length:32\r\n\r\n" ++
+ "<HTML><BODY>foobar</BODY></HTML>";
+
+handle_uri(_,"/once_chunked.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ send(Socket,
+ http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+
+handle_uri(_,"/once.html",_,_,Socket,_) ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:32\r\n\r\n",
+ send(Socket, Head),
+ send(Socket, "<HTML><BODY>fo"),
+ test_server:sleep(1000),
+ send(Socket, "ob"),
+ test_server:sleep(1000),
+ send(Socket, "ar</BODY></HTML>");
+
+handle_uri(_,"/invalid_http.html",_,_,_,_) ->
+ "HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
+ "Transfer-Encoding:chunked\r\n\r\n";
+
+handle_uri(_,"/missing_reason_phrase.html",_,_,_,_) ->
+ "HTTP/1.1 200\r\n" ++
+ "Content-Length: 32\r\n\r\n"
+ "<HTML><BODY>foobar</BODY></HTML>";
+
+handle_uri(_,"/missing_CR.html",_,_,_,_) ->
+ "HTTP/1.1 200 ok\n" ++
+ "Content-Length:32\r\n\n" ++
+ "<HTML><BODY>foobar</BODY></HTML>";
+
+handle_uri("HEAD",_,_,_,_,_) ->
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:0\r\n\r\n";
+handle_uri(_,_,_,_,_,DefaultResponse) ->
+ DefaultResponse.
+
+url_start(#sslsocket{}) ->
+ {ok,Host} = inet:gethostname(),
+ ?TLS_URL_START ++ Host ++ ":";
+url_start(_) ->
+ {ok,Host} = inet:gethostname(),
+ ?URL_START ++ Host ++ ":".
+
+send(#sslsocket{} = S, Msg) ->
+ ssl:send(S, Msg);
+send(S, Msg) ->
+ gen_tcp:send(S, Msg).
+
+close(#sslsocket{} = S) ->
+ ssl:close(S);
+close(S) ->
+ gen_tcp:close(S).
+
+sockname(#sslsocket{}= S) ->
+ ssl:sockname(S);
+sockname(S) ->
+ inet:sockname(S).
+
+receive_streamed_body(RequestId, Body) ->
+ receive
+ {http, {RequestId, stream, BinBodyPart}} ->
+ receive_streamed_body(RequestId,
+ <<Body/binary, BinBodyPart/binary>>);
+ {http, {RequestId, stream_end, _Headers}} ->
+ Body;
+ {http, Msg} ->
+ ct:fail(Msg)
end.
-pick_header(Headers, Name) ->
- case lists:keysearch(string:to_lower(Name), 1,
- [{string:to_lower(X), Y} || {X, Y} <- Headers]) of
- false ->
- [];
- {value, {_Key, Val}} ->
- Val
+receive_streamed_body(RequestId, Body, Pid) ->
+ httpc:stream_next(Pid),
+ ct:print("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
+ receive
+ {http, {RequestId, stream, BinBodyPart}} ->
+ %% Make sure the httpc hasn't sent us the next 'stream'
+ %% without our request.
+ receive
+ {http, {RequestId, stream, _}} = Msg ->
+ ct:fail({unexpected_flood_of_stream, Msg})
+ after
+ 1000 ->
+ ok
+ end,
+ receive_streamed_body(RequestId,
+ <<Body/binary, BinBodyPart/binary>>,
+ Pid);
+ {http, {RequestId, stream_end, _Headers}} ->
+ Body;
+ {http, Msg} ->
+ ct:fail(Msg)
end.
+%% -----------------------------------------------------
+%% A sequence number handler
+%% The purpose is to be able to pair requests with responses.
-%% -------------------------------------------------------------------------
-
-simple_request_and_verify(Config,
- Method, Request, HttpOpts, Opts, VerifyResult)
- when (is_list(Config) andalso
- is_atom(Method) andalso
- is_list(HttpOpts) andalso
- is_list(Opts) andalso
- is_function(VerifyResult, 1)) ->
- tsp("request_and_verify -> entry with"
- "~n Method: ~p"
- "~n Request: ~p"
- "~n HttpOpts: ~p"
- "~n Opts: ~p", [Method, Request, HttpOpts, Opts]),
- case ?config(local_server, Config) of
- ok ->
- tsp("request_and_verify -> local-server running"),
- Result = (catch httpc:request(Method, Request, HttpOpts, Opts)),
- VerifyResult(Result);
- _ ->
- tsp("request_and_verify -> local-server *not* running - skip"),
- hard_skip("Local http-server not running")
+start_sequence_number_server() ->
+ proc_lib:spawn(fun() -> loop_sequence_number(1) end).
+
+loop_sequence_number(N) ->
+ receive
+ shutdown ->
+ ok;
+ {From, get_next} ->
+ From ! {next_is, N},
+ loop_sequence_number(N + 1)
+ end.
+
+get_next_sequence_number(SeqNumServer) ->
+ SeqNumServer ! {self(), get_next},
+ receive {next_is, N} -> N end.
+
+%% -----------------------------------------------------
+%% Client part
+%% Sends requests randomly parallel
+
+run_clients(NumClients, ServerPort, SeqNumServer) ->
+ {ok,Host} = inet:gethostname(),
+ set_random_seed(),
+ lists:map(
+ fun(Id) ->
+ Req = lists:flatten(io_lib:format("req~3..0w", [get_next_sequence_number(SeqNumServer)])),
+ Url = ?URL_START ++ Host ++ ":" ++ integer_to_list(ServerPort) ++ "/" ++ Req,
+ Pid = proc_lib:spawn(
+ fun() ->
+ case httpc:request(Url) of
+ {ok, {{_,200,_}, _, Resp}} ->
+ ct:print("[~w] 200 response: "
+ "~p~n", [Id, Resp]),
+ case lists:prefix(Req++"->", Resp) of
+ true -> exit(normal);
+ false -> exit({bad_resp,Req,Resp})
+ end;
+ {ok, {{_,EC,Reason},_,Resp}} ->
+ ct:print("[~w] ~w response: "
+ "~s~n~s~n",
+ [Id, EC, Reason, Resp]),
+ exit({bad_resp,Req,Resp});
+ Crap ->
+ ct:print("[~w] bad response: ~p",
+ [Id, Crap]),
+ exit({bad_resp, Req, Crap})
+ end
+ end),
+ MRef = erlang:monitor(process, Pid),
+ timer:sleep(10 + random:uniform(1334)),
+ {Id, Pid, MRef}
+ end,
+ lists:seq(1, NumClients)).
+
+wait4clients([], _Timeout) ->
+ ok;
+wait4clients(Clients, Timeout) when Timeout > 0 ->
+ Time = now_ms(),
+ receive
+ {'DOWN', _MRef, process, Pid, normal} ->
+ {value, {Id, _, _}} = lists:keysearch(Pid, 2, Clients),
+ NewClients = lists:keydelete(Id, 1, Clients),
+ wait4clients(NewClients, Timeout - (now_ms() - Time));
+ {'DOWN', _MRef, process, Pid, Reason} ->
+ {value, {Id, _, _}} = lists:keysearch(Pid, 2, Clients),
+ ct:fail({bad_client_termination, Id, Reason})
+ after Timeout ->
+ ct:fail({client_timeout, Clients})
+ end;
+wait4clients(Clients, _) ->
+ ct:fail({client_timeout, Clients}).
+
+
+%% -----------------------------------------------------
+%% Webserver part:
+%% Implements a web server that sends responses one character
+%% at a time, with random delays between the characters.
+
+start_slow_server(SeqNumServer) ->
+ proc_lib:start(
+ erlang, apply, [fun() -> init_slow_server(SeqNumServer) end, []]).
+
+init_slow_server(SeqNumServer) ->
+ Inet = inet_version(),
+ {ok, LSock} = gen_tcp:listen(0, [binary, Inet, {packet,0}, {active,true},
+ {backlog, 100}]),
+ {ok, {_IP, Port}} = inet:sockname(LSock),
+ proc_lib:init_ack({ok, self(), Port}),
+ loop_slow_server(LSock, SeqNumServer).
+
+loop_slow_server(LSock, SeqNumServer) ->
+ Master = self(),
+ Acceptor = proc_lib:spawn(
+ fun() -> client_handler(Master, LSock, SeqNumServer) end),
+ receive
+ {accepted, Acceptor} ->
+ loop_slow_server(LSock, SeqNumServer);
+ shutdown ->
+ gen_tcp:close(LSock),
+ exit(Acceptor, kill)
end.
+%% Handle one client connection
+client_handler(Master, LSock, SeqNumServer) ->
+ {ok, CSock} = gen_tcp:accept(LSock),
+ Master ! {accepted, self()},
+ set_random_seed(),
+ loop_client(1, CSock, SeqNumServer).
+loop_client(N, CSock, SeqNumServer) ->
+ %% Await request, don't bother parsing it too much,
+ %% assuming the entire request arrives in one packet.
+ receive
+ {tcp, CSock, Req} ->
+ ReqNum = parse_req_num(Req),
+ RespSeqNum = get_next_sequence_number(SeqNumServer),
+ Response = lists:flatten(io_lib:format("~s->resp~3..0w/~2..0w", [ReqNum, RespSeqNum, N])),
+ Txt = lists:flatten(io_lib:format("Slow server (~p) got ~p, answering with ~p",
+ [self(), Req, Response])),
+ ct:print("~s...~n", [Txt]),
+ slowly_send_response(CSock, Response),
+ case parse_connection_type(Req) of
+ keep_alive ->
+ ct:print("~s...done~n", [Txt]),
+ loop_client(N+1, CSock, SeqNumServer);
+ close ->
+ ct:print("~s...done (closing)~n", [Txt]),
+ gen_tcp:close(CSock)
+ end
+ end.
-not_implemented_yet() ->
- exit(not_implemented_yet).
+slowly_send_response(CSock, Answer) ->
+ Response = lists:flatten(io_lib:format("HTTP/1.1 200 OK\r\nContent-Length: ~w\r\n\r\n~s",
+ [length(Answer), Answer])),
+ lists:foreach(
+ fun(Char) ->
+ timer:sleep(random:uniform(500)),
+ gen_tcp:send(CSock, <<Char>>)
+ end,
+ Response).
-p(F) ->
- p(F, []).
+parse_req_num(Request) ->
+ Opts = [caseless,{capture,all_but_first,list}],
+ {match, [ReqNum]} = re:run(Request, "GET /(.*) HTTP", Opts),
+ ReqNum.
-p(F, A) ->
- io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
+parse_connection_type(Request) ->
+ Opts = [caseless,{capture,all_but_first,list}],
+ {match,[CType]} = re:run(Request, "connection: *(keep-alive|close)", Opts),
+ case string:to_lower(CType) of
+ "close" -> close;
+ "keep-alive" -> keep_alive
+ end.
-tsp(F) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
-tsp(F, A) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
+%% Time in milli seconds
+now_ms() ->
+ {A,B,C} = erlang:now(),
+ A*1000000000+B*1000+(C div 1000).
-tsf(Reason) ->
- test_server:fail(Reason).
+set_random_seed() ->
+ {_, _, Micros} = now(),
+ A = erlang:phash2([make_ref(), self(), Micros]),
+ random:seed(A, A, A).
-dummy_ssl_server_hang(Caller, IpV, SslOpt) ->
- Pid = spawn(httpc_SUITE, dummy_ssl_server_hang_init, [Caller, IpV, SslOpt]),
+otp_8739(doc) ->
+ ["OTP-8739"];
+otp_8739(suite) ->
+ [];
+otp_8739(Config) when is_list(Config) ->
+ {_DummyServerPid, Port} = otp_8739_dummy_server(),
+ {ok,Host} = inet:gethostname(),
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ "/dummy.html",
+ Method = get,
+ Request = {URL, []},
+ HttpOptions = [{connect_timeout, 500}, {timeout, 1}],
+ Options = [{sync, true}],
+ case httpc:request(Method, Request, HttpOptions, Options) of
+ {error, timeout} ->
+ %% And now we check the size of the handler db
+ Info = httpc:info(),
+ ct:print("Info: ~p", [Info]),
+ {value, {handlers, Handlers}} =
+ lists:keysearch(handlers, 1, Info),
+ case Handlers of
+ [] ->
+ ok;
+ _ ->
+ ct:fail({unexpected_handlers, Handlers})
+ end;
+ Unexpected ->
+ ct:fail({unexpected, Unexpected})
+ end.
+
+otp_8739_dummy_server() ->
+ Parent = self(),
+ Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end),
receive
{port, Port} ->
{Pid, Port}
end.
-dummy_ssl_server_hang_init(Caller, IpV, SslOpt) ->
+otp_8739_dummy_server_init(Parent) ->
+ Inet = inet_version(),
{ok, ListenSocket} =
- case IpV of
- ipv4 ->
- ssl:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}] ++ SslOpt);
- ipv6 ->
- ssl:listen(0, [binary, inet6, {packet, 0},
- {reuseaddr,true},
- {active, false}] ++ SslOpt)
- end,
- {ok, {_,Port}} = ssl:sockname(ListenSocket),
- tsp("dummy_ssl_server_hang_init -> Port: ~p", [Port]),
- Caller ! {port, Port},
- {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
- dummy_ssl_server_hang_loop(AcceptSocket).
+ gen_tcp:listen(0, [binary, Inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}]),
+ {ok, Port} = inet:port(ListenSocket),
+ Parent ! {port, Port},
+ otp_8739_dummy_server_main(Parent, ListenSocket).
-dummy_ssl_server_hang_loop(_) ->
- %% Do not do ssl:ssl_accept as we
- %% want to time out the underlying gen_tcp:connect
- receive
- stop ->
- ok
+otp_8739_dummy_server_main(_Parent, ListenSocket) ->
+ case gen_tcp:accept(ListenSocket) of
+ {ok, Sock} ->
+ %% Ignore the request, and simply wait for the socket to close
+ receive
+ {tcp_closed, Sock} ->
+ (catch gen_tcp:close(ListenSocket)),
+ exit(normal);
+ {tcp_error, Sock, Reason} ->
+ ct:fail("socket error: ~p", [Reason]),
+ (catch gen_tcp:close(ListenSocket)),
+ exit(normal)
+ after 10000 ->
+ %% Just in case
+ (catch gen_tcp:close(Sock)),
+ (catch gen_tcp:close(ListenSocket)),
+ exit(timeout)
+ end;
+ Error ->
+ exit(Error)
end.
-
-hard_skip(Reason) ->
- throw(skip(Reason)).
-
-skip(Reason) ->
- {skip, Reason}.
diff --git a/lib/inets/test/httpc_SUITE_data/ssl_client_cert.pem b/lib/inets/test/httpc_SUITE_data/ssl_client_cert.pem
index f274d2021d..427447958d 100644
--- a/lib/inets/test/httpc_SUITE_data/ssl_client_cert.pem
+++ b/lib/inets/test/httpc_SUITE_data/ssl_client_cert.pem
@@ -1,22 +1,31 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIBOwIBAAJBANz7eFvORmJDi1XJMM2U3uHC5wmp/DXTLMw08XaEvtZ73wgVg84E
-V0oyX3Kh1thRE3Hch9AyrHjgpizCj9/Ra38CAwEAAQJACzpz2SZYCTIpaEh6xFdm
-I86FcsZCXHHIeu/NvRntoHQ+nfM7Np379+z6XNJWIcWh/QgG/jNJalR1BO+eyc6/
-YQIhAP3m8M0LDxJwSgHFtGAGatQqaqw9l48Kq5xdMFqvdpiHAiEA3s7lld6yCJYu
-6q7fZjTH+eKUwgg0vpgJutP7Fsok60kCIHHesQBEhW3vjkFdOZgXSLH+k/jLZr1w
-O6bU5GrHZpjhAiEAyTvGYcjDtTunXjDY9l+fadK6FlEBCk8ZIpNIiTnDhHkCIQDr
-QxxLLuNHRj8iWNbuVVZ99SJy8zC33pMgPFaFKaZesQ==
+MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n
+0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr
+3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB
+AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB
+I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna
+QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f
+eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws
+/LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI
+ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV
+LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj
+40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6
+UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80
+t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-MIIB7jCCAZgCAQAwDQYJKoZIhvcNAQEEBQAwgYExCzAJBgNVBAYTAlNFMRIwEAYD
-VQQHEwlTdG9ja2hvbG0xETAPBgNVBAoTCEVyaWNzc29uMQwwCgYDVQQLEwNFVFgx
-FjAUBgNVBAMTDUhlbGVuIEFpcml5YW4xJTAjBgkqhkiG9w0BCQEWFmhlbGVuQGVy
-aXguZXJpY3Nzb24uc2UwHhcNOTcwNzI4MDcxNDI1WhcNOTgxMjEwMDcxNDI1WjCB
-gTELMAkGA1UEBhMCU0UxEjAQBgNVBAcTCVN0b2NraG9sbTERMA8GA1UEChMIRXJp
-Y3Nzb24xDDAKBgNVBAsTA0VUWDEWMBQGA1UEAxMNSGVsZW4gQWlyaXlhbjElMCMG
-CSqGSIb3DQEJARYWaGVsZW5AZXJpeC5lcmljc3Nvbi5zZTBcMA0GCSqGSIb3DQEB
-AQUAA0sAMEgCQQDc+3hbzkZiQ4tVyTDNlN7hwucJqfw10yzMNPF2hL7We98IFYPO
-BFdKMl9yodbYURNx3IfQMqx44KYswo/f0Wt/AgMBAAEwDQYJKoZIhvcNAQEEBQAD
-QQC2++hLIaQJ4ChCjFE9UCfXO9cZ3Vq/FT9VjE+G4MRBDo4LQ5mBKNXcPF6EFZmi
-7XrlvopXkVPlRguTi2SLRPkY
+MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
+BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
+BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
+VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
+MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
+cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
+VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV
+wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53
+h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID
+AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A
+PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD
+4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ
+S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5
-----END CERTIFICATE-----
diff --git a/lib/inets/test/httpc_SUITE_data/ssl_server_cert.pem b/lib/inets/test/httpc_SUITE_data/ssl_server_cert.pem
index f01b6c992b..4aac86db49 100644
--- a/lib/inets/test/httpc_SUITE_data/ssl_server_cert.pem
+++ b/lib/inets/test/httpc_SUITE_data/ssl_server_cert.pem
@@ -1,22 +1,31 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIBOQIBAAJBAMe2WhP6s+JeKOwWPEjI9susfN4Vjn2dd1X4QUlOETcWVLoF916m
-M4JU+ms7+ciMR8GRNCsIeqZGY8/GSqm74ccCAwEAAQJAF08YKlbLYfM9cXiS5qfV
-7iWemUkIzW5wfC8yZ3zeE4Cp6R9ViUfs/dadQ/23Cw0Bpo2t8UdTUdCa4KpmqOem
-cQIhAOnxTWZ5eo6h6PXDp7L5FZUACg8+wT3qf5f2is2mbSZPAiEA2orUY8JZDTSk
-Rm7q9WxLiLNtORsXdTCmnCWhqBOYpwkCIErdowRxScxNekz0IT3AQqzdR1rbnWHg
-IpcSGhd39CQ3AiA1XvQxjLP8wp9fyBS/bPwhXVhOOuyGpSP7PEF3b5m3KQIgGQWc
-/a5wuWx3pc3mLx0ILwNoJr2ubFEuW1PJPsPJPv0=
+MIICXQIBAAKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9Adq6
+7k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ4UAt
+NHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQIDAQAB
+AoGAQIlma0r6W6bcRj4+Wd4fXCFvHuq5Psu1fYEeC5Yvz8761xVjjSfbrDHJZ9pm
+FjOEgedK+s5lbDXqYVyjbdyZSugStBRocSmbG8SQHcAsxR2ZIkNzX2hYzB+lslWo
+T3YJojDyB134O7XJznCu+ZFXP86jyJ1JT6k6a+OIHcwnJ+ECQQDYn57dY4Px3mEd
+VBLStN3YkRF5oFyT+xk7IaKeLLB6n4gCnoVbBoHut7PFbPYPzoNzEwPk3MQKDIHb
+Kig3S5CpAkEAvPA1VmoJWAlN6kUi+F2L8HXEArzE8x7vwdsslrwMKUe4dFS+ZC/7
+5iDOaxcZ7TYkCgwzBt341++DCgP6j3fY1QJBALB6AcOcwi52m6l4B8mu3ZkEPjdX
+BHTuONTqhv/TqoaLlxODL2NDvvDKqeMp7KBd/srt79swW2lQXS4+fvrlTdkCQQCm
+zxj4O1QWkthkfje6ubSkTwUIOatUzrp1F9GNH2dJRtX2dx9FCwxGCC7WY6XzRXqa
+GF0wsedSllbGD+82nWQlAkAicMGqCqRq4hKR/cVmFatOqKVWCVkx6OFF2FhuiI5Z
+h5eIOPGCt8dVRs1P9DNSld/D98Sfm65m85z8BtXovvYV
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-MIIB7jCCAZgCAQAwDQYJKoZIhvcNAQEEBQAwgYExCzAJBgNVBAYTAlNFMRIwEAYD
-VQQHEwlTdG9ja2hvbG0xETAPBgNVBAoTCEVyaWNzc29uMQwwCgYDVQQLEwNFVFgx
-FjAUBgNVBAMTDUhlbGVuIEFpcml5YW4xJTAjBgkqhkiG9w0BCQEWFmhlbGVuQGVy
-aXguZXJpY3Nzb24uc2UwHhcNOTcwNzI4MDcyMTAwWhcNOTgxMjEwMDcyMTAwWjCB
-gTELMAkGA1UEBhMCU0UxEjAQBgNVBAcTCVN0b2NraG9sbTERMA8GA1UEChMIRXJp
-Y3Nzb24xDDAKBgNVBAsTA0VUWDEWMBQGA1UEAxMNSGVsZW4gQWlyaXlhbjElMCMG
-CSqGSIb3DQEJARYWaGVsZW5AZXJpeC5lcmljc3Nvbi5zZTBcMA0GCSqGSIb3DQEB
-AQUAA0sAMEgCQQDHtloT+rPiXijsFjxIyPbLrHzeFY59nXdV+EFJThE3FlS6Bfde
-pjOCVPprO/nIjEfBkTQrCHqmRmPPxkqpu+HHAgMBAAEwDQYJKoZIhvcNAQEEBQAD
-QQCnU1TkxmfbLdUwjdECb5x9QHCevAR7AmTms4Csn2oOEyPX+bgF2d94xhrV1sxO
-Rs0yigk1PtN17Ci0Dey0LYkR
+MIIChzCCAfCgAwIBAgIGANUxXM9BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
+BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
+BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
+VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
+MDAwWjB7MQ8wDQYDVQQDEwZzZXJ2ZXIxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
+cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
+VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9
+Adq67k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ
+4UAtNHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQID
+AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAGF5Pfwk
+QDdwJup/mVITPxbBls4Yl7anDooUQsq8066lA1g54H/PRfXscGkyCFGh1ifXvf1L
+psMRoBAdDHL/wSJplk3rRavkC94eBgnTFZmfKL6844g1j53yameiYL8IEVExYMBg
+/XGyc0qwq57WT8B/K4aElrvlBlQ0wF3wN54M
-----END CERTIFICATE-----
diff --git a/lib/inets/test/httpc_cookie_SUITE.erl b/lib/inets/test/httpc_cookie_SUITE.erl
index 93dbc270c5..3862bf7a20 100644
--- a/lib/inets/test/httpc_cookie_SUITE.erl
+++ b/lib/inets/test/httpc_cookie_SUITE.erl
@@ -276,8 +276,6 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> entry with"
"~n Config: ~p", [Config]),
- inets:enable_trace(max, io, httpc),
-
%% httpc:reset_cookies(),
tsp("secure_cookie -> Cookies 1: ~p", [httpc:which_cookies()]),
@@ -309,7 +307,6 @@ secure_cookie(Config) when is_list(Config) ->
tsp("secure_cookie -> Cookies 4: ~p", [httpc:which_cookies()]),
- inets:disable_trace(),
tsp("secure_cookie -> done"),
ok.
diff --git a/lib/inets/test/httpc_proxy_SUITE.erl b/lib/inets/test/httpc_proxy_SUITE.erl
new file mode 100644
index 0000000000..ef277f2b01
--- /dev/null
+++ b/lib/inets/test/httpc_proxy_SUITE.erl
@@ -0,0 +1,592 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%
+%% ts:run(inets, httpc_proxy_SUITE, [batch]).
+%% ct:run("../inets_test", httpc_proxy_SUITE).
+%%
+
+-module(httpc_proxy_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-include_lib("kernel/include/file.hrl").
+-include("inets_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(LOCAL_PROXY_SCRIPT, "server_proxy.sh").
+-define(p(F, A), % Debug printout
+ begin
+ io:format(
+ "~w ~w: " ++ begin F end,
+ [self(),?MODULE] ++ begin A end)
+ end).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [{group,local_proxy},
+ {group,local_proxy_https}].
+
+groups() ->
+ [{local_proxy,[],
+ [http_emulate_lower_versions
+ |local_proxy_cases()]},
+ {local_proxy_https,[],
+ local_proxy_cases()}].
+
+%% internal functions
+
+local_proxy_cases() ->
+ [http_head,
+ http_get,
+ http_options,
+ http_trace,
+ http_post,
+ http_put,
+ http_delete,
+ http_delete_body,
+ http_headers,
+ http_proxy_auth,
+ http_doesnotexist,
+ http_stream,
+ http_not_modified_otp_6821].
+
+%%--------------------------------------------------------------------
+
+init_per_suite(Config0) ->
+ case init_apps([crypto,public_key], Config0) of
+ Config when is_list(Config) ->
+ make_cert_files(dsa, "server-", Config),
+ Config;
+ Other ->
+ Other
+ end.
+
+end_per_suite(_Config) ->
+ [app_stop(App) || App <- r(suite_apps())],
+ ok.
+
+%% internal functions
+
+suite_apps() ->
+ [crypto,public_key].
+
+%%--------------------------------------------------------------------
+
+init_per_group(local_proxy, Config) ->
+ init_local_proxy([{protocol,http}|Config]);
+init_per_group(local_proxy_https, Config) ->
+ init_local_proxy([{protocol,https}|Config]).
+
+end_per_group(Group, Config)
+ when
+ Group =:= local_proxy;
+ Group =:= local_proxy_https ->
+ rcmd_local_proxy(["stop"], Config),
+ Config;
+end_per_group(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+
+init_per_testcase(Case, Config0) ->
+ ct:timetrap({seconds,30}),
+ Apps = apps(Case, Config0),
+ case init_apps(Apps, Config0) of
+ Config when is_list(Config) ->
+ case app_start(inets, Config) of
+ ok ->
+ Config;
+ Error ->
+ [app_stop(N) || N <- [inets|r(Apps)]],
+ ct:fail({could_not_init_inets,Error})
+ end;
+ E3 ->
+ E3
+ end.
+
+end_per_testcase(_Case, Config) ->
+ app_stop(inets),
+ Config.
+
+%% internal functions
+
+apps(_Case, Config) ->
+ case ?config(protocol, Config) of
+ https ->
+ [ssl];
+ _ ->
+ []
+ end.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+http_head(doc) ->
+ ["Test http/https HEAD request."];
+http_head(Config) when is_list(Config) ->
+ Method = head,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,200,_},[_|_],[]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_get(doc) ->
+ ["Test http/https GET request."];
+http_get(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ Timeout = timer:seconds(1),
+ ConnTimeout = Timeout + timer:seconds(1),
+
+ HttpOpts1 = [{timeout,Timeout},{connect_timeout,ConnTimeout}],
+ Opts1 = [],
+ {ok,{{_,200,_},[_|_],[_|_]=B1}} =
+ httpc:request(Method, Request, HttpOpts1, Opts1),
+ inets_test_lib:check_body(B1),
+
+ HttpOpts2 = [],
+ Opts2 = [{body_format,binary}],
+ {ok,{{_,200,_},[_|_],B2}} =
+ httpc:request(Method, Request, HttpOpts2, Opts2),
+ inets_test_lib:check_body(binary_to_list(B2)).
+
+%%--------------------------------------------------------------------
+
+http_options(doc) ->
+ ["Perform an OPTIONS request."];
+http_options(Config) when is_list(Config) ->
+ Method = options,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,200,_},Headers,_}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ {value,_} = lists:keysearch("allow", 1, Headers),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_trace(doc) ->
+ ["Perform a TRACE request."];
+http_trace(Config) when is_list(Config) ->
+ Method = trace,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,200,_},[_|_],"TRACE "++_}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_post(doc) ->
+ ["Perform a POST request that goes through a proxy. When the "
+ "request goes to an ordinary file it seems the POST data "
+ "is ignored."];
+http_post(Config) when is_list(Config) ->
+ Method = post,
+ URL = url("/index.html", Config),
+ Request = {URL,[],"text/plain","foobar"},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,200,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_put(doc) ->
+ ["Perform a PUT request. The server will not allow it "
+ "but we only test sending the request."];
+http_put(Config) when is_list(Config) ->
+ Method = put,
+ URL = url("/put.html", Config),
+ Content =
+ "<html><body> <h1>foo</h1> <p>bar</p> </body></html>",
+ Request = {URL,[],"html",Content},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,405,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_delete(doc) ->
+ ["Perform a DELETE request that goes through a proxy. Note the server "
+ "will reject the request with a 405 Method Not Allowed,"
+ "but this is just a test of sending the request."];
+http_delete(Config) when is_list(Config) ->
+ Method = delete,
+ URL = url("/delete.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,405,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_delete_body(doc) ->
+ ["Perform a DELETE request with a content body. The server will not allow it "
+ "but we only test sending the request."];
+http_delete_body(Config) when is_list(Config) ->
+ Method = delete,
+ URL = url("/delete.html", Config),
+ Content = "foo=bar",
+ Request = {URL,[],"application/x-www-form-urlencoded",Content},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,405,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_headers(doc) ->
+ ["Use as many request headers as possible"];
+http_headers(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/index.html", Config),
+ Headers =
+ [{"Accept",
+ "text/*, text/html, text/html;level=1, */*"},
+ {"Accept-Charset",
+ "iso-8859-5, unicode-1-1;q=0.8"},
+ {"Accept-Encoding", "*"},
+ {"Accept-Language",
+ "sv, en-gb;q=0.8, en;q=0.7"},
+ {"User-Agent", "inets"},
+ {"Max-Forwards","5"},
+ {"Referer",
+ "http://otp.ericsson.se:8000/product/internal"}],
+ Request = {URL,Headers},
+ HttpOpts = [],
+ Opts = [],
+ {ok,{{_,200,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_proxy_auth(doc) ->
+ ["Test the code for sending of proxy authorization."];
+http_proxy_auth(Config) when is_list(Config) ->
+ %% Our proxy seems to ignore the header, however our proxy
+ %% does not requirer an auth header, but we want to know
+ %% atleast the code for sending the header does not crash!
+ Method = get,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [{proxy_auth,{"foo","bar"}}],
+ Opts = [],
+ {ok,{{_,200,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_doesnotexist(doc) ->
+ ["Test that we get a 404 when the page is not found."];
+http_doesnotexist(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/doesnotexist.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [{proxy_auth,{"foo","bar"}}],
+ Opts = [],
+ {ok,{{_,404,_},[_|_],[_|_]}} =
+ httpc:request(Method, Request, HttpOpts, Opts),
+ ok.
+
+%%--------------------------------------------------------------------
+
+http_stream(doc) ->
+ ["Test the option stream for asynchronous requests"];
+http_stream(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ HttpOpts = [],
+
+ Opts1 = [{body_format,binary}],
+ {ok,{{_,200,_},[_|_],Body}} =
+ httpc:request(Method, Request, HttpOpts, Opts1),
+
+ Opts2 = [{sync,false},{stream,self}],
+ {ok,RequestId} =
+ httpc:request(Method, Request, HttpOpts, Opts2),
+ receive
+ {http,{RequestId,stream_start,[_|_]}} ->
+ ok
+ end,
+ case http_stream(RequestId, <<>>) of
+ Body -> ok
+ end.
+ %% StreamedBody = http_stream(RequestId, <<>>),
+ %% Body =:= StreamedBody,
+ %% ok.
+
+http_stream(RequestId, Body) ->
+ receive
+ {http,{RequestId,stream,Bin}} ->
+ http_stream(RequestId, <<Body/binary,Bin/binary>>);
+ {http,{RequestId,stream_end,_Headers}} ->
+ Body
+ end.
+
+%%--------------------------------------------------------------------
+
+http_emulate_lower_versions(doc) ->
+ ["Perform requests as 0.9 and 1.0 clients."];
+http_emulate_lower_versions(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/index.html", Config),
+ Request = {URL,[]},
+ Opts = [],
+
+ HttpOpts1 = [{version,"HTTP/0.9"}],
+ {ok,[_|_]=B1} =
+ httpc:request(Method, Request, HttpOpts1, Opts),
+ inets_test_lib:check_body(B1),
+
+ HttpOpts2 = [{version,"HTTP/1.0"}],
+ {ok,{{_,200,_},[_|_],[_|_]=B2}} =
+ httpc:request(Method, Request, HttpOpts2, Opts),
+ inets_test_lib:check_body(B2),
+
+ HttpOpts3 = [{version,"HTTP/1.1"}],
+ {ok,{{_,200,_},[_|_],[_|_]=B3}} =
+ httpc:request(Method, Request, HttpOpts3, Opts),
+ inets_test_lib:check_body(B3),
+
+ ok.
+
+%%--------------------------------------------------------------------
+http_not_modified_otp_6821(doc) ->
+ ["If unmodified no body should be returned"];
+http_not_modified_otp_6821(Config) when is_list(Config) ->
+ Method = get,
+ URL = url("/index.html", Config),
+ Opts = [],
+
+ Request1 = {URL,[]},
+ HttpOpts1 = [],
+ {ok,{{_,200,_},ReplyHeaders,[_|_]}} =
+ httpc:request(Method, Request1, HttpOpts1, Opts),
+ ETag = header_value("etag", ReplyHeaders),
+ LastModified = header_value("last-modified", ReplyHeaders),
+
+ Request2 =
+ {URL,
+ [{"If-None-Match",ETag},
+ {"If-Modified-Since",LastModified}]},
+ HttpOpts2 = [{timeout,15000}], % Limit wait for bug result
+ {ok,{{_,304,_},_,[]}} = % Page Unchanged
+ httpc:request(Method, Request2, HttpOpts2, Opts),
+
+ ok.
+
+header_value(Name, [{HeaderName,HeaderValue}|Headers]) ->
+ case string:to_lower(HeaderName) of
+ Name ->
+ HeaderValue;
+ _ ->
+ header_value(Name, Headers)
+ end.
+
+%%--------------------------------------------------------------------
+%% Internal Functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+init_apps([], Config) ->
+ Config;
+init_apps([App|Apps], Config) ->
+ case app_start(App, Config) of
+ ok ->
+ init_apps(Apps, Config);
+ Error ->
+ Msg =
+ lists:flatten(
+ io_lib:format(
+ "Could not start ~p due to ~p.~n",
+ [App, Error])),
+ {skip,Msg}
+ end.
+
+app_start(App, Config) ->
+ try
+ case App of
+ crypto ->
+ crypto:stop(),
+ ok = crypto:start();
+ inets ->
+ application:stop(App),
+ ok = application:start(App),
+ case ?config(proxy, Config) of
+ undefined -> ok;
+ {_,ProxySpec} ->
+ ok = httpc:set_options([{proxy,ProxySpec}])
+ end;
+ _ ->
+ application:stop(App),
+ ok = application:start(App)
+ end
+ catch
+ Class:Reason ->
+ {exception,Class,Reason}
+ end.
+
+app_stop(App) ->
+ application:stop(App).
+
+make_cert_files(Alg, Prefix, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ CaInfo = {CaCert,_} = erl_make_certs:make_cert([{key,Alg}]),
+ {Cert,CertKey} = erl_make_certs:make_cert([{key,Alg},{issuer,CaInfo}]),
+ CaCertFile = filename:join(PrivDir, Prefix++"cacerts.pem"),
+ CertFile = filename:join(PrivDir, Prefix++"cert.pem"),
+ KeyFile = filename:join(PrivDir, Prefix++"key.pem"),
+ der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
+ der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
+ der_to_pem(KeyFile, [CertKey]),
+ ok.
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).
+
+
+
+url(AbsPath, Config) ->
+ Protocol = ?config(protocol, Config),
+ {ServerName,ServerPort} = ?config(Protocol, Config),
+ atom_to_list(Protocol) ++ "://" ++
+ ServerName ++ ":" ++ integer_to_list(ServerPort) ++
+ AbsPath.
+
+%%--------------------------------------------------------------------
+
+init_local_proxy(Config) ->
+ case os:type() of
+ {unix,_} ->
+ case rcmd_local_proxy(["start"], Config) of
+ {0,[":STARTED:"++String]} ->
+ init_local_proxy_string(String, Config);
+ {_,[":SKIP:"++_|_]}=Reason ->
+ {skip,Reason};
+ Error ->
+ rcmd_local_proxy(["stop"], Config),
+ ct:fail({local_proxy_start_failed,Error})
+ end;
+ _ ->
+ {skip,"Platform can not run local proxy start script"}
+ end.
+
+init_local_proxy_string(String, Config) ->
+ {Proxy,Server} = split($|, String),
+ {ProxyName,ProxyPort} = split($:, Proxy),
+ {ServerName,ServerPorts} = split($:, Server),
+ {ServerHttpPort,ServerHttpsPort} = split($:, ServerPorts),
+ [{proxy,{local,{{ProxyName,list_to_integer(ProxyPort)},[]}}},
+ {http,{ServerName,list_to_integer(ServerHttpPort)}},
+ {https,{ServerName,list_to_integer(ServerHttpsPort)}}
+ |Config].
+
+rcmd_local_proxy(Args, Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ Script = filename:join(DataDir, ?LOCAL_PROXY_SCRIPT),
+ rcmd(Script, Args, [{cd,PrivDir}]).
+
+rcmd(Cmd, Args, Opts) ->
+ Port =
+ erlang:open_port(
+ {spawn_executable,Cmd},
+ [{args,Args},{line,80},exit_status,eof,hide|Opts]),
+ rcmd_loop(Port, [], [], undefined, false).
+
+rcmd_loop(Port, Lines, Buf, Exit, EOF) ->
+ receive
+ {Port,{data,{Flag,Line}}} ->
+ case Flag of
+ noeol ->
+ rcmd_loop(Port, Lines, r(Line, Buf), Exit, EOF);
+ eol ->
+ rcmd_loop(Port, [r(Buf, Line)|Lines], [], Exit, EOF)
+ end;
+ {Port,{exit_status,Status}} when Exit =:= undefined ->
+ case EOF of
+ true ->
+ rcmd_close(Port, Lines, Buf, Status);
+ false ->
+ rcmd_loop(Port, Lines, Buf, Status, EOF)
+ end;
+ {Port,eof} when EOF =:= false ->
+ case Exit of
+ undefined ->
+ rcmd_loop(Port, Lines, Buf, Exit, true);
+ Status ->
+ rcmd_close(Port, Lines, Buf, Status)
+ end;
+ {Port,_}=Unexpected ->
+ ct:fail({unexpected_from_port,Unexpected})
+ end.
+
+rcmd_close(Port, Lines, Buf, Status) ->
+ catch port_close(Port),
+ case Buf of
+ [] ->
+ {Status,Lines};
+ _ ->
+ {Status,[r(Buf)|Lines]}
+ end.
+
+%%--------------------------------------------------------------------
+
+%% Split on first match of X in Ys, do not include X in neither part
+split(X, Ys) ->
+ split(X, Ys, []).
+%%
+split(X, [X|Ys], Rs) ->
+ {r(Rs),Ys};
+split(X, [Y|Ys], Rs) ->
+ split(X, Ys, [Y|Rs]).
+
+r(L) -> lists:reverse(L).
+r(L, R) -> lists:reverse(L, R).
diff --git a/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf b/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf
new file mode 100644
index 0000000000..37af88c510
--- /dev/null
+++ b/lib/inets/test/httpc_proxy_SUITE_data/apache2/apache2.conf
@@ -0,0 +1,87 @@
+## Simple Apache 2 configuration file for daily test very local http server
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2012. All Rights Reserved.
+##
+## The contents of this file are subject to the Erlang Public License,
+## Version 1.1, (the "License"); you may not use this file except in
+## compliance with the License. You should have received a copy of the
+## Erlang Public License along with this software. If not, it can be
+## retrieved online at http://www.erlang.org/.
+##
+## Software distributed under the License is distributed on an "AS IS"
+## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+## the License for the specific language governing rights and limitations
+## under the License.
+##
+## %CopyrightEnd%
+##
+## Author: Raimo Niskanen, Erlang/OTP
+#
+LockFile ${APACHE_LOCK_DIR}/accept.lock
+PidFile ${APACHE_PID_FILE}
+
+Timeout 300
+
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+DefaultType text/plain
+HostnameLookups Off
+ErrorLog ${APACHE_LOG_DIR}/error.log
+LogLevel warn
+
+Include ${APACHE_MODS_DIR}/*.load
+Include ${APACHE_MODS_DIR}/*.conf
+
+Listen ${APACHE_HTTP_PORT} http
+
+<IfModule mod_ssl.c>
+ Listen ${APACHE_HTTPS_PORT} https
+ SSLMutex file:${APACHE_LOCK_DIR}/ssl_mutex
+</IfModule>
+
+#<IfModule mod_gnutls.c>
+# Listen 8443
+#</IfModule>
+
+#LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+#LogFormat "%h %l %u %t \"%r\" %>s %O" common
+#LogFormat "%{Referer}i -> %U" referer
+#LogFormat "%{User-agent}i" agent
+
+CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+<Directory />
+ AllowOverride None
+ Order Deny,Allow
+ Deny from all
+</Directory>
+
+ServerTokens Minimal
+ServerSignature Off
+KeepAlive On
+KeepAliveTimeout 5
+
+ServerName ${APACHE_SERVER_NAME}
+ServerAdmin webmaster@${APACHE_SERVER_NAME}
+DocumentRoot ${APACHE_DOCROOT}
+<Directory ${APACHE_DOCROOT}>
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+<VirtualHost *:${APACHE_HTTP_PORT}>
+</VirtualHost>
+
+<IfModule mod_ssl.c>
+ <VirtualHost *:${APACHE_HTTPS_PORT}>
+ SSLCertificateFile ${APACHE_CERTS_DIR}/server-cert.pem
+ SSLCertificateKeyFile ${APACHE_CERTS_DIR}/server-key.pem
+ SSLEngine on
+ </VirtualHost>
+</IfModule>
diff --git a/lib/inets/test/httpc_proxy_SUITE_data/apache2/htdocs/index.html b/lib/inets/test/httpc_proxy_SUITE_data/apache2/htdocs/index.html
new file mode 100644
index 0000000000..1c70d95348
--- /dev/null
+++ b/lib/inets/test/httpc_proxy_SUITE_data/apache2/htdocs/index.html
@@ -0,0 +1,4 @@
+<html><body><h1>It works!</h1>
+<p>This is the default web page for this server.</p>
+<p>The web server software is running but no content has been added, yet.</p>
+</body></html>
diff --git a/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh
new file mode 100755
index 0000000000..d5f18c937f
--- /dev/null
+++ b/lib/inets/test/httpc_proxy_SUITE_data/server_proxy.sh
@@ -0,0 +1,198 @@
+#! /bin/sh
+##
+## Command file to handle external webserver and proxy
+## apache2 and tinyproxy.
+##
+## %CopyrightBegin%
+##
+## Copyright Ericsson AB 2012. All Rights Reserved.
+##
+## The contents of this file are subject to the Erlang Public License,
+## Version 1.1, (the "License"); you may not use this file except in
+## compliance with the License. You should have received a copy of the
+## Erlang Public License along with this software. If not, it can be
+## retrieved online at http://www.erlang.org/.
+##
+## Software distributed under the License is distributed on an "AS IS"
+## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+## the License for the specific language governing rights and limitations
+## under the License.
+##
+## %CopyrightEnd%
+##
+## Author: Raimo Niskanen, Erlang/OTP
+#
+
+PATH=/usr/local/bin:/usr/local/sbin:/bin:/usr/bin:/sbin:/usr/sbin
+SHELL=/bin/sh
+unset CDPATH ENV BASH_ENV
+IFS='
+ '
+
+APACHE_MODS_AVAILABLE_DIR="/etc/apache2/mods-available"
+MODS="authz_host.load mime.conf mime.load ssl.conf ssl.load"
+
+APACHE_HTTP_PORT=8080
+APACHE_HTTPS_PORT=8443
+APACHE_SERVER_NAME=localhost
+export APACHE_HTTP_PORT APACHE_HTTPS_PORT APACHE_SERVER_NAME
+
+PROXY_SERVER_NAME=localhost
+PROXY_PORT=8000
+export PROXY_SERVER_NAME PROXY_PORT
+
+# All stdout goes to the calling erlang port, therefore
+# these helpers push all side info to stderr.
+status () { echo "$@"; }
+info () { echo "$@" 1>&2; }
+die () { REASON="$?"; status "$@"; exit "$REASON"; }
+cmd () { "$@" 1>&2; }
+silent () { "$@" 1>/dev/null 2>&1; }
+
+wait_for_pidfile () {
+ PIDFILE="${1:?Missing argument: PidFile}"
+ for t in 1 1 1 2 2 3 3 3 4; do
+ PID="`head -1 "$1" 2>/dev/null`" && [ :"$PID" != : ] && break
+ sleep $t
+ done
+ [ :"$PID" = : ] && die ":ERROR:No or empty PidFile: $1"
+ info "Started $PIDFILE[$PID]."
+}
+
+kill_and_wait () {
+ PID_FILE="${1:?Missing argument: PidFile}"
+ if [ -f "$PID_FILE" ]; then
+ PID="`head -1 "$PID_FILE" 2>/dev/null`"
+ [ :"$PID" = : ] && \
+ info "Empty Pid file: $1"
+ info "Stopping $1 [$PID]..."
+ shift
+ case :"${1:?Missing argument: kill command}" in
+ :kill)
+ [ :"$PID" = : ] || cmd kill "$PID";;
+ :*)
+ cmd "$@";;
+ esac
+ wait "$PID"
+ for t in 1 1 1 2; do
+ sleep $t
+ [ -e "$PID_FILE" ] || break
+ done
+ silent rm "$PID_FILE"
+ else
+ info "No pid file: $1"
+ fi
+}
+
+
+PRIV_DIR="`pwd`"
+DATA_DIR="`dirname "$0"`"
+DATA_DIR="`cd "$DATA_DIR" && pwd`"
+
+silent type apache2ctl || \
+ die ":SKIP: Can not find apache2ctl."
+silent type tinyproxy || \
+ die ":SKIP: Can not find tinyproxy."
+
+[ -d "$APACHE_MODS_AVAILABLE_DIR" ] || \
+ die ":SKIP:Can not locate modules dir $APACHE_MODS_AVAILABLE_DIR."
+
+silent mkdir apache2 tinyproxy
+cd apache2 || \
+ die ":ERROR:Can not cd to apache2"
+CWD="`pwd`"
+(cd ../tinyproxy) || \
+ die ":ERROR:Can not cd to ../tinyproxy"
+
+unset APACHE_HTTPD APACHE_LYNX APACHE_STATUSURL
+
+## apache2ctl envvars variables
+APACHE_CONFDIR="$DATA_DIR/apache2"
+[ -f "$APACHE_CONFDIR"/apache2.conf ] || \
+ die ":SKIP:No config file: $APACHE_CONFDIR/apache2.conf."
+APACHE_RUN_USER=`id | sed 's/^uid=[0-9]\{1,\}(\([^)]*\)).*/\1/'`
+APACHE_RUN_GROUP=`id | sed 's/.*[ ]gid=[0-9]\{1,\}(\([^)]*\)).*/\1/'`
+APACHE_RUN_DIR="$CWD/run"
+APACHE_PID_FILE="$APACHE_RUN_DIR/pid"
+APACHE_LOCK_DIR="$CWD/lock"
+APACHE_LOG_DIR="$CWD/log"
+export APACHE_CONFDIR APACHE_RUN_USER APACHE_RUN_GROUP
+export APACHE_RUN_DIR APACHE_PID_FILE
+export APACHE_LOCK_DIR APACHE_LOG_DIR
+silent cmd mkdir "$APACHE_CONFDIR"
+silent cmd mkdir "$APACHE_RUN_DIR" "$APACHE_LOCK_DIR" "$APACHE_LOG_DIR"
+
+## Our apache2.conf additional variables
+APACHE_MODS_DIR="$CWD/mods"
+APACHE_DOCROOT="$APACHE_CONFDIR/htdocs"
+APACHE_CERTS_DIR="$PRIV_DIR"
+export APACHE_MODS_DIR APACHE_DOCROOT APACHE_CERTS_DIR
+[ -d "$APACHE_MODS_DIR" ] || {
+ cmd mkdir "$APACHE_MODS_DIR"
+ for MOD in $MODS; do
+ cmd ln -s "$APACHE_MODS_AVAILABLE_DIR/$MOD" "$APACHE_MODS_DIR" || {
+ die ":ERROR:ln of apache 2 module $MOD failed"
+ }
+ done
+}
+
+case :"${1:?}" in
+
+ :start)
+ info "Starting apache2..."
+ cmd apache2ctl start
+ [ $? = 0 ] || \
+ die ":ERROR: apache2 did not start."
+ wait_for_pidfile "$APACHE_PID_FILE"
+
+ info "Starting tinyproxy..."
+ cmd cd ../tinyproxy || \
+ die ":ERROR:Can not cd to `pwd`/../tinyproxy"
+ cat >tinyproxy.conf <<EOF
+Port $PROXY_PORT
+
+Listen 127.0.0.1
+BindSame yes
+Timeout 600
+
+DefaultErrorFile "default.html"
+Logfile "tinyproxy.log"
+PidFile "tinyproxy.pid"
+
+MaxClients 100
+MinSpareServers 2
+MaxSpareServers 8
+StartServers 2
+MaxRequestsPerChild 0
+
+ViaProxyName "tinyproxy"
+
+ConnectPort $APACHE_HTTPS_PORT
+EOF
+ (tinyproxy -d -c tinyproxy.conf 1>/dev/null 2>&1 </dev/null &)&
+ wait_for_pidfile tinyproxy.pid
+
+ status ":STARTED:$PROXY_SERVER_NAME:$PROXY_PORT|\
+$APACHE_SERVER_NAME:$APACHE_HTTP_PORT:$APACHE_HTTPS_PORT"
+ exit 0
+ ;;
+
+ :stop)
+ kill_and_wait ../tinyproxy/tinyproxy.pid kill
+ kill_and_wait "$APACHE_PID_FILE" apache2ctl stop
+
+ status ":STOPPED:"
+ exit 0
+ ;;
+
+ :apache2ctl)
+ shift
+ cmd apache2ctl ${1+"$@"}
+ exit
+ ;;
+
+ :*)
+ (exit 1); die ":ERROR: I do not know of command '$1'."
+ ;;
+
+esac
diff --git a/lib/inets/test/httpd_1_0.erl b/lib/inets/test/httpd_1_0.erl
new file mode 100644
index 0000000000..6059546057
--- /dev/null
+++ b/lib/inets/test/httpd_1_0.erl
@@ -0,0 +1,33 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013-2014. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(httpd_1_0).
+
+-export([host/4]).
+
+%%-------------------------------------------------------------------------
+%% Test cases
+%%-------------------------------------------------------------------------
+host(Type, Port, Host, Node) ->
+ %% No host needed for HTTP/1.0
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET / HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]).
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index 07d94ea97a..9d2b623772 100644
--- a/lib/inets/test/httpd_1_1.erl
+++ b/lib/inets/test/httpd_1_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -20,8 +20,6 @@
-module(httpd_1_1).
--include("test_server.hrl").
--include("test_server_line.hrl").
-include_lib("kernel/include/file.hrl").
-export([host/4, chunked/4, expect/4, range/4, if_test/5, http_trace/4,
@@ -40,14 +38,10 @@
%%-------------------------------------------------------------------------
-%% Test cases starts here.
+%% Test cases
%%-------------------------------------------------------------------------
host(Type, Port, Host, Node) ->
- %% No host needed for HTTP/1.0
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- "GET / HTTP/1.0\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
+
%% No host must generate an error
ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
"GET / HTTP/1.1\r\n\r\n",
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 41e4188e5f..74b85acd3f 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -1,8 +1,8 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2013-2014. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
@@ -18,2546 +18,736 @@
%%
%%
--module(httpd_SUITE).
+%%
+%% ct:run("../inets_test", httpd_SUITE).
+%%
--include_lib("test_server/include/test_server.hrl").
--include("test_server_line.hrl").
--include("inets_test_lib.hrl").
+-module(httpd_SUITE).
-include_lib("kernel/include/file.hrl").
+-include_lib("common_test/include/ct.hrl").
+-include("inets_test_lib.hrl").
-%% Test server specific exports
--export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
--export([init_per_testcase/2, end_per_testcase/2,
- init_per_suite/1, end_per_suite/1]).
-
-%% Core Server tests
--export([
- ip_mod_alias/1,
- ip_mod_actions/1,
- ip_mod_security/1,
- ip_mod_auth/1,
- ip_mod_auth_api/1,
- ip_mod_auth_mnesia_api/1,
- ip_mod_htaccess/1,
- ip_mod_cgi/1,
- ip_mod_esi/1,
- ip_mod_get/1,
- ip_mod_head/1,
- ip_mod_all/1,
- ip_load_light/1,
- ip_load_medium/1,
- ip_load_heavy/1,
- ip_dos_hostname/1,
- ip_time_test/1,
- ip_block_disturbing_idle/1,
- ip_block_non_disturbing_idle/1,
- ip_block_503/1,
- ip_block_disturbing_active/1,
- ip_block_non_disturbing_active/1,
- ip_block_disturbing_active_timeout_not_released/1,
- ip_block_disturbing_active_timeout_released/1,
- ip_block_non_disturbing_active_timeout_not_released/1,
- ip_block_non_disturbing_active_timeout_released/1,
- ip_block_disturbing_blocker_dies/1,
- ip_block_non_disturbing_blocker_dies/1,
- ip_restart_no_block/1,
- ip_restart_disturbing_block/1,
- ip_restart_non_disturbing_block/1
- ]).
-
--export([
- pssl_mod_alias/1,
- essl_mod_alias/1,
-
- pssl_mod_actions/1,
- essl_mod_actions/1,
-
- pssl_mod_security/1,
- essl_mod_security/1,
-
- pssl_mod_auth/1,
- essl_mod_auth/1,
-
- pssl_mod_auth_api/1,
- essl_mod_auth_api/1,
-
- pssl_mod_auth_mnesia_api/1,
- essl_mod_auth_mnesia_api/1,
-
- pssl_mod_htaccess/1,
- essl_mod_htaccess/1,
-
- pssl_mod_cgi/1,
- essl_mod_cgi/1,
-
- pssl_mod_esi/1,
- essl_mod_esi/1,
-
- pssl_mod_get/1,
- essl_mod_get/1,
-
- pssl_mod_head/1,
- essl_mod_head/1,
-
- pssl_mod_all/1,
- essl_mod_all/1,
-
- pssl_load_light/1,
- essl_load_light/1,
-
- pssl_load_medium/1,
- essl_load_medium/1,
-
- pssl_load_heavy/1,
- essl_load_heavy/1,
-
- pssl_dos_hostname/1,
- essl_dos_hostname/1,
-
- pssl_time_test/1,
- essl_time_test/1,
-
- pssl_restart_no_block/1,
- essl_restart_no_block/1,
-
- pssl_restart_disturbing_block/1,
- essl_restart_disturbing_block/1,
-
- pssl_restart_non_disturbing_block/1,
- essl_restart_non_disturbing_block/1,
-
- pssl_block_disturbing_idle/1,
- essl_block_disturbing_idle/1,
-
- pssl_block_non_disturbing_idle/1,
- essl_block_non_disturbing_idle/1,
-
- pssl_block_503/1,
- essl_block_503/1,
-
- pssl_block_disturbing_active/1,
- essl_block_disturbing_active/1,
-
- pssl_block_non_disturbing_active/1,
- essl_block_non_disturbing_active/1,
-
- pssl_block_disturbing_active_timeout_not_released/1,
- essl_block_disturbing_active_timeout_not_released/1,
-
- pssl_block_disturbing_active_timeout_released/1,
- essl_block_disturbing_active_timeout_released/1,
-
- pssl_block_non_disturbing_active_timeout_not_released/1,
- essl_block_non_disturbing_active_timeout_not_released/1,
-
- pssl_block_non_disturbing_active_timeout_released/1,
- essl_block_non_disturbing_active_timeout_released/1,
-
- pssl_block_disturbing_blocker_dies/1,
- essl_block_disturbing_blocker_dies/1,
-
- pssl_block_non_disturbing_blocker_dies/1,
- essl_block_non_disturbing_blocker_dies/1
- ]).
-
-%%% HTTP 1.1 tests
--export([ip_host/1, ip_chunked/1, ip_expect/1, ip_range/1,
- ip_if_test/1, ip_http_trace/1, ip_http1_1_head/1,
- ip_mod_cgi_chunked_encoding_test/1]).
-
-%%% HTTP 1.0 tests
--export([ip_head_1_0/1, ip_get_1_0/1, ip_post_1_0/1]).
-
-%%% HTTP 0.9 tests
--export([ip_get_0_9/1]).
-
-%%% Ticket tests
--export([ticket_5775/1,ticket_5865/1,ticket_5913/1,ticket_6003/1,
- ticket_7304/1]).
-
-%%% IPv6 tests
--export([ipv6_hostname_ipcomm/0, ipv6_hostname_ipcomm/1,
- ipv6_address_ipcomm/0, ipv6_address_ipcomm/1,
- ipv6_hostname_essl/0, ipv6_hostname_essl/1,
- ipv6_address_essl/0, ipv6_address_essl/1]).
-
-%% Help functions
--export([cleanup_mnesia/0, setup_mnesia/0, setup_mnesia/1]).
-
--define(IP_PORT, 8898).
--define(SSL_PORT, 8899).
--define(MAX_HEADER_SIZE, 256).
--define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1").
-
-%% Minutes before failed auths timeout.
--define(FAIL_EXPIRE_TIME,1).
-
-%% Seconds before successful auths timeout.
--define(AUTH_TIMEOUT,5).
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
-record(httpd_user, {user_name, password, user_data}).
-record(httpd_group, {group_name, userlist}).
-
%%--------------------------------------------------------------------
-%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
-%% Arg - doc | suite
-%% Doc - string()
-%% Case - atom()
-%% Name of a test case function.
-%% Comment - string()
-%% Description: Returns documentation/test cases in this test suite
-%% or a skip tuple if the platform is not supported.
+%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-suite() -> [{ct_hooks,[ts_install_cth]}].
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
-all() ->
+all() ->
[
- {group, ip},
- {group, ssl},
- {group, http_1_1_ip},
- {group, http_1_0_ip},
- {group, http_0_9_ip},
- {group, ipv6},
- {group, tickets}
+ {group, http},
+ {group, http_limit}
+ %%{group, https}
].
-groups() ->
+groups() ->
[
- {ip, [],
- [ip_mod_alias, ip_mod_actions, ip_mod_security,
- ip_mod_auth, ip_mod_auth_api, ip_mod_auth_mnesia_api,
- ip_mod_htaccess, ip_mod_cgi, ip_mod_esi, ip_mod_get,
- ip_mod_head, ip_mod_all, ip_load_light, ip_load_medium,
- ip_load_heavy, ip_dos_hostname, ip_time_test,
- ip_restart_no_block, ip_restart_disturbing_block,
- ip_restart_non_disturbing_block,
- ip_block_disturbing_idle, ip_block_non_disturbing_idle,
- ip_block_503, ip_block_disturbing_active,
- ip_block_non_disturbing_active,
- ip_block_disturbing_active_timeout_not_released,
- ip_block_disturbing_active_timeout_released,
- ip_block_non_disturbing_active_timeout_not_released,
- ip_block_non_disturbing_active_timeout_released,
- ip_block_disturbing_blocker_dies,
- ip_block_non_disturbing_blocker_dies]},
- {ssl, [], [{group, pssl}, {group, essl}]},
- {pssl, [],
- [pssl_mod_alias, pssl_mod_actions, pssl_mod_security,
- pssl_mod_auth, pssl_mod_auth_api,
- pssl_mod_auth_mnesia_api, pssl_mod_htaccess,
- pssl_mod_cgi, pssl_mod_esi, pssl_mod_get, pssl_mod_head,
- pssl_mod_all, pssl_load_light, pssl_load_medium,
- pssl_load_heavy, pssl_dos_hostname, pssl_time_test,
- pssl_restart_no_block, pssl_restart_disturbing_block,
- pssl_restart_non_disturbing_block,
- pssl_block_disturbing_idle,
- pssl_block_non_disturbing_idle, pssl_block_503,
- pssl_block_disturbing_active,
- pssl_block_non_disturbing_active,
- pssl_block_disturbing_active_timeout_not_released,
- pssl_block_disturbing_active_timeout_released,
- pssl_block_non_disturbing_active_timeout_not_released,
- pssl_block_non_disturbing_active_timeout_released,
- pssl_block_disturbing_blocker_dies,
- pssl_block_non_disturbing_blocker_dies]},
- {essl, [],
- [essl_mod_alias, essl_mod_actions, essl_mod_security,
- essl_mod_auth, essl_mod_auth_api,
- essl_mod_auth_mnesia_api, essl_mod_htaccess,
- essl_mod_cgi, essl_mod_esi, essl_mod_get, essl_mod_head,
- essl_mod_all, essl_load_light, essl_load_medium,
- essl_load_heavy, essl_dos_hostname, essl_time_test,
- essl_restart_no_block, essl_restart_disturbing_block,
- essl_restart_non_disturbing_block,
- essl_block_disturbing_idle,
- essl_block_non_disturbing_idle, essl_block_503,
- essl_block_disturbing_active,
- essl_block_non_disturbing_active,
- essl_block_disturbing_active_timeout_not_released,
- essl_block_disturbing_active_timeout_released,
- essl_block_non_disturbing_active_timeout_not_released,
- essl_block_non_disturbing_active_timeout_released,
- essl_block_disturbing_blocker_dies,
- essl_block_non_disturbing_blocker_dies]},
- {http_1_1_ip, [],
- [ip_host, ip_chunked, ip_expect, ip_range, ip_if_test,
- ip_http_trace, ip_http1_1_head,
- ip_mod_cgi_chunked_encoding_test]},
- {http_1_0_ip, [],
- [ip_head_1_0, ip_get_1_0, ip_post_1_0]},
- {http_0_9_ip, [], [ip_get_0_9]},
- {ipv6, [], [ipv6_hostname_ipcomm, ipv6_address_ipcomm,
- ipv6_hostname_essl, ipv6_address_essl]},
- {tickets, [],
- [ticket_5775, ticket_5865, ticket_5913, ticket_6003,
- ticket_7304]}].
-
-
-init_per_group(ipv6 = _GroupName, Config) ->
- case inets_test_lib:has_ipv6_support() of
- {ok, _} ->
- Config;
- _ ->
- {skip, "Host does not support IPv6"}
- end;
-init_per_group(_GroupName, Config) ->
- Config.
+ {http, [], all_groups()},
+ %%{https, [], all_groups()},
+ {http_limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
+ {http_1_1, [], [host, chunked, expect, cgi] ++ http_head() ++ http_get()},
+ {http_1_0, [], [host, cgi] ++ http_head() ++ http_get()},
+ {http_0_9, [], http_head() ++ http_get()}
+ ].
-end_per_group(_GroupName, Config) ->
- Config.
+all_groups ()->
+ [{group, http_1_1},
+ {group, http_1_0},
+ {group, http_0_9}
+ ].
+http_head() ->
+ [head].
+http_get() ->
+ [alias, get,
+ basic_auth,
+ esi, ssi].
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
init_per_suite(Config) ->
- io:format(user, "init_per_suite -> entry with"
- "~n Config: ~p"
- "~n", [Config]),
-
- ?PRINT_SYSTEM_INFO([]),
-
PrivDir = ?config(priv_dir, Config),
- SuiteTopDir = filename:join(PrivDir, ?MODULE),
- case file:make_dir(SuiteTopDir) of
- ok ->
- ok;
- {error, eexist} ->
- ok;
- Error ->
- throw({error, {failed_creating_suite_top_dir, Error}})
- end,
-
- [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
- {suite_top_dir, SuiteTopDir},
+ DataDir = ?config(data_dir, Config),
+ inets_test_lib:stop_apps([inets]),
+ inets_test_lib:start_apps([inets]),
+ ServerRoot = filename:join(PrivDir, "server_root"),
+ inets_test_lib:del_dirs(ServerRoot),
+ DocRoot = filename:join(ServerRoot, "htdocs"),
+ setup_server_dirs(ServerRoot, DocRoot, DataDir),
+ [{server_root, ServerRoot},
+ {doc_root, DocRoot},
{node, node()},
- {host, inets_test_lib:hostname()},
- {address, getaddr()} | Config].
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
+ {host, inets_test_lib:hostname()} | Config].
end_per_suite(_Config) ->
- %% SuiteTopDir = ?config(suite_top_dir, Config),
- %% inets_test_lib:del_dirs(SuiteTopDir),
ok.
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(Case, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
-init_per_testcase(Case, Config) ->
- NewConfig = init_per_testcase2(Case, Config),
- init_per_testcase3(Case, NewConfig).
-
-
-init_per_testcase2(Case, Config) ->
-
- tsp("init_per_testcase2 -> entry with"
- "~n Config: ~p", [Config]),
-
- IpNormal = integer_to_list(?IP_PORT) ++ ".conf",
- IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf",
- SslNormal = integer_to_list(?SSL_PORT) ++ ".conf",
- SslHtaccess = integer_to_list(?SSL_PORT) ++ "htaccess.conf",
-
- DataDir = ?config(data_dir, Config),
- SuiteTopDir = ?config(suite_top_dir, Config),
-
- tsp("init_per_testcase2 -> "
- "~n SuiteDir: ~p"
- "~n DataDir: ~p", [SuiteTopDir, DataDir]),
-
- TcTopDir = filename:join(SuiteTopDir, Case),
- ?line ok = file:make_dir(TcTopDir),
-
- tsp("init_per_testcase2 -> "
- "~n TcTopDir: ~p", [TcTopDir]),
-
- DataSrc = filename:join([DataDir, "server_root"]),
- ServerRoot = filename:join([TcTopDir, "server_root"]),
-
- tsp("init_per_testcase2 -> "
- "~n DataSrc: ~p"
- "~n ServerRoot: ~p", [DataSrc, ServerRoot]),
-
- ok = file:make_dir(ServerRoot),
- ok = file:make_dir(filename:join([TcTopDir, "logs"])),
-
- NewConfig = [{tc_top_dir, TcTopDir}, {server_root, ServerRoot} | Config],
-
- tsp("init_per_testcase2 -> copy DataSrc to ServerRoot"),
-
- inets_test_lib:copy_dirs(DataSrc, ServerRoot),
-
- tsp("init_per_testcase2 -> fix cgi"),
- EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]),
- {ok, FileInfo} = file:read_file_info(EnvCGI),
- ok = file:write_file_info(EnvCGI,
- FileInfo#file_info{mode = 8#00755}),
-
- EchoCGI = case test_server:os_type() of
- {win32, _} ->
- "cgi_echo.exe";
- _ ->
- "cgi_echo"
- end,
- CGIDir = filename:join([ServerRoot, "cgi-bin"]),
- inets_test_lib:copy_file(EchoCGI, DataDir, CGIDir),
- NewEchoCGI = filename:join([CGIDir, EchoCGI]),
- {ok, FileInfo1} = file:read_file_info(NewEchoCGI),
- ok = file:write_file_info(NewEchoCGI,
- FileInfo1#file_info{mode = 8#00755}),
-
- %% To be used by IP test cases
- tsp("init_per_testcase2 -> ip testcase setups"),
- create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
- normal_access, IpNormal),
- create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
- mod_htaccess, IpHtaccess),
-
- %% To be used by SSL test cases
- tsp("init_per_testcase2 -> ssl testcase setups"),
- SocketType =
- case atom_to_list(Case) of
- [X, $s, $s, $l | _] ->
- case X of
- $p -> ssl;
- $e -> essl
- end;
- _ ->
- ssl
- end,
-
- create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
- normal_access, SslNormal),
- create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
- mod_htaccess, SslHtaccess),
-
- %% To be used by IPv6 test cases. Case-clause is so that
- %% you can do ts:run(inets, httpd_SUITE, <test case>)
- %% for all cases except the ipv6 cases as they depend
- %% on 'test_host_ipv6_only' that will only be present
- %% when you run the whole test suite due to shortcomings
- %% of the test server.
-
- tsp("init_per_testcase2 -> maybe generate IPv6 config file(s)"),
- NewConfig2 =
- case atom_to_list(Case) of
- "ipv6_" ++ _ ->
- case (catch inets_test_lib:has_ipv6_support(NewConfig)) of
- {ok, IPv6Address0} ->
- {ok, Hostname} = inet:gethostname(),
- IPv6Address = http_transport:ipv6_name(IPv6Address0),
- create_ipv6_config([{port, ?IP_PORT},
- {sock_type, ip_comm},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_hostname_ipcomm.conf",
- Hostname),
- create_ipv6_config([{port, ?IP_PORT},
- {sock_type, ip_comm},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_address_ipcomm.conf",
- IPv6Address),
- create_ipv6_config([{port, ?SSL_PORT},
- {sock_type, essl},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_hostname_essl.conf",
- Hostname),
- create_ipv6_config([{port, ?SSL_PORT},
- {sock_type, essl},
- {ipv6_host, IPv6Address} |
- NewConfig],
- "ipv6_address_essl.conf",
- IPv6Address),
- [{ipv6_host, IPv6Address} | NewConfig];
- _ ->
- NewConfig
- end;
-
- _ ->
- NewConfig
- end,
-
- tsp("init_per_testcase2 -> done when"
- "~n NewConfig2: ~p", [NewConfig2]),
-
- NewConfig2.
-
-
-init_per_testcase3(Case, Config) ->
- tsp("init_per_testcase3(~w) -> entry with"
- "~n Config: ~p", [Case, Config]),
-
-
-%% %% Create a new fresh node to be used by the server in this test-case
-
-%% NodeName = list_to_atom(atom_to_list(Case) ++ "_httpd"),
-%% Node = inets_test_lib:start_node(NodeName),
-
- %% Clean up (we do not want this clean up in end_per_testcase
- %% if init_per_testcase crashes for some testcase it will
- %% have contaminated the environment and there will be no clean up.)
- %% This init can take a few different paths so that one crashes
- %% does not mean that all invocations will.
-
- application:unset_env(inets, services),
- application:stop(inets),
- application:stop(ssl),
- cleanup_mnesia(),
-
- %% Set trace level
- case lists:reverse(atom_to_list(Case)) of
- "tset_emit" ++ _Rest -> % test-cases ending with time_test
- tsp("init_per_testcase3(~w) -> disabling trace", [Case]),
- inets:disable_trace();
+init_per_group(https = Group, Config0) ->
+ case start_apps(Group) of
+ ok ->
+ init_httpd(Group, [{type, ssl} | Config0]);
_ ->
- tsp("init_per_testcase3(~w) -> enabling trace", [Case]),
- %% TraceLevel = 70,
- TraceLevel = max,
- TraceDest = io,
- inets:enable_trace(TraceLevel, TraceDest, httpd)
- end,
-
- %% Start initialization
- tsp("init_per_testcase3(~w) -> start init", [Case]),
-
-
- Dog = test_server:timetrap(inets_test_lib:minutes(10)),
- NewConfig = lists:keydelete(watchdog, 1, Config),
- TcTopDir = ?config(tc_top_dir, Config),
- CaseRest =
- case atom_to_list(Case) of
- "ip_mod_htaccess" ->
- inets_test_lib:start_http_server(
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++
- "htaccess.conf")),
- "mod_htaccess";
- "ip_" ++ Rest ->
- inets_test_lib:start_http_server(
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++ ".conf")),
- Rest;
- "ticket_5913" ->
- HttpdOptions =
- [{file,
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++ ".conf")},
- {accept_timeout,30000},
- {debug,[{exported_functions,
- [httpd_manager,httpd_request_handler]}]}],
- inets_test_lib:start_http_server(HttpdOptions);
- "ticket_"++Rest ->
- %% OTP-5913 use the new syntax of inets.config
- inets_test_lib:start_http_server([{file,
- filename:join(TcTopDir,
- integer_to_list(?IP_PORT) ++ ".conf")}]),
- Rest;
-
- [X, $s, $s, $l, $_, $m, $o, $d, $_, $h, $t, $a, $c, $c, $e, $s, $s] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- SslTag =
- case X of
- $p -> ssl; % Plain
- $e -> essl % Erlang based ssl
- end,
- case inets_test_lib:start_http_server_ssl(
- filename:join(TcTopDir,
- integer_to_list(?SSL_PORT) ++
- "htaccess.conf"), SslTag) of
- ok ->
- "mod_htaccess";
- Other ->
- error_logger:info_msg("Other: ~p~n", [Other]),
- {skip, "SSL does not seem to be supported"}
- end;
- [X, $s, $s, $l, $_ | Rest] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- SslTag =
- case X of
- $p -> ssl;
- $e -> essl
- end,
- case inets_test_lib:start_http_server_ssl(
- filename:join(TcTopDir,
- integer_to_list(?SSL_PORT) ++
- ".conf"), SslTag) of
- ok ->
- Rest;
- Other ->
- error_logger:info_msg("Other: ~p~n", [Other]),
- {skip, "SSL does not seem to be supported"}
- end;
- "ipv6_" ++ _ = TestCaseStr ->
- case inets_test_lib:has_ipv6_support() of
- {ok, _} ->
- inets_test_lib:start_http_server(
- filename:join(TcTopDir,
- TestCaseStr ++ ".conf"));
-
- _ ->
- {skip, "Host does not support IPv6"}
- end
- end,
-
- InitRes =
- case CaseRest of
- {skip, _} = Skip ->
- Skip;
- "mod_auth_" ++ _ ->
- start_mnesia(?config(node, Config)),
- [{watchdog, Dog} | NewConfig];
- "mod_htaccess" ->
- ServerRoot = ?config(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- catch remove_htaccess(Path),
- create_htaccess_data(Path, ?config(address, Config)),
- [{watchdog, Dog} | NewConfig];
- "range" ->
- ServerRoot = ?config(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- create_range_data(Path),
- [{watchdog, Dog} | NewConfig];
- _ ->
- [{watchdog, Dog} | NewConfig]
- end,
-
- tsp("init_per_testcase3(~w) -> done when"
- "~n InitRes: ~p", [Case, InitRes]),
-
- InitRes.
-
+ {skip, "Could not start https apps"}
+ end;
+init_per_group(Group, Config0) when Group == http; Group == http_limit ->
+ init_httpd(Group, [{type, ip_comm} | Config0]);
+init_per_group(http_1_1, Config) ->
+ [{http_version, "HTTP/1.1"} | Config];
+init_per_group(http_1_0, Config) ->
+ [{http_version, "HTTP/1.0"} | Config];
+init_per_group(http_0_9, Config) ->
+ [{http_version, "HTTP/0.9"} | Config];
+init_per_group(_, Config) ->
+ Config.
+end_per_group(http, _Config) ->
+ ok;
+end_per_group(https, _Config) ->
+ ssl:stop();
+end_per_group(_, _) ->
+ ok.
+
+init_httpd(Group, Config0) ->
+ Config1 = proplists:delete(port, Config0),
+ Config = proplists:delete(server_pid, Config1),
+ {Pid, Port} = server_start(Group, server_config(Group, Config)),
+ [{server_pid, Pid}, {port, Port} | Config].
%%--------------------------------------------------------------------
-%% Function: end_per_testcase(Case, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(Case, Config) ->
- Dog = ?config(watchdog, Config),
- test_server:timetrap_cancel(Dog),
- end_per_testcase2(Case, lists:keydelete(watchdog, 1, Config)),
- ok.
-
-end_per_testcase2(Case, Config) ->
- tsp("end_per_testcase2(~w) -> entry with"
- "~n Config: ~p", [Case, Config]),
- application:unset_env(inets, services),
- application:stop(inets),
- application:stop(ssl),
- application:stop(crypto), % used by the new ssl (essl test cases)
- cleanup_mnesia(),
- tsp("end_per_testcase2(~w) -> done", [Case]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-
-%%-------------------------------------------------------------------------
-ip_mod_alias(doc) ->
- ["Module test: mod_alias"];
-ip_mod_alias(suite) ->
- [];
-ip_mod_alias(Config) when is_list(Config) ->
- httpd_mod:alias(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_actions(doc) ->
- ["Module test: mod_actions"];
-ip_mod_actions(suite) ->
- [];
-ip_mod_actions(Config) when is_list(Config) ->
- httpd_mod:actions(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_security(doc) ->
- ["Module test: mod_security"];
-ip_mod_security(suite) ->
- [];
-ip_mod_security(Config) when is_list(Config) ->
- ServerRoot = ?config(server_root, Config),
- httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_auth(doc) ->
- ["Module test: mod_auth"];
-ip_mod_auth(suite) ->
- [];
-ip_mod_auth(Config) when is_list(Config) ->
- httpd_mod:auth(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_auth_api(doc) ->
- ["Module test: mod_auth_api"];
-ip_mod_auth_api(suite) ->
- [];
-ip_mod_auth_api(Config) when is_list(Config) ->
- ServerRoot = ?config(server_root, Config),
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- httpd_mod:auth_api(ServerRoot, "", ip_comm, ?IP_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "dets_", ip_comm, ?IP_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "mnesia_", ip_comm, ?IP_PORT, Host, Node),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api"];
-ip_mod_auth_mnesia_api(suite) ->
- [];
-ip_mod_auth_mnesia_api(Config) when is_list(Config) ->
- httpd_mod:auth_mnesia_api(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_htaccess(doc) ->
- ["Module test: mod_htaccess"];
-ip_mod_htaccess(suite) ->
- [];
-ip_mod_htaccess(Config) when is_list(Config) ->
- httpd_mod:htaccess(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_cgi(doc) ->
- ["Module test: mod_cgi"];
-ip_mod_cgi(suite) ->
- [];
-ip_mod_cgi(Config) when is_list(Config) ->
- case test_server:os_type() of
- vxworks ->
- {skip, cgi_not_supported_on_vxwoks};
- _ ->
- httpd_mod:cgi(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok
- end.
-%%-------------------------------------------------------------------------
-ip_mod_esi(doc) ->
- ["Module test: mod_esi"];
-ip_mod_esi(suite) ->
- [];
-ip_mod_esi(Config) when is_list(Config) ->
- httpd_mod:esi(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_get(doc) ->
- ["Module test: mod_get"];
-ip_mod_get(suite) ->
- [];
-ip_mod_get(Config) when is_list(Config) ->
- httpd_mod:get(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_head(doc) ->
- ["Module test: mod_head"];
-ip_mod_head(suite) ->
- [];
-ip_mod_head(Config) when is_list(Config) ->
- httpd_mod:head(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_all(doc) ->
- ["All modules test"];
-ip_mod_all(suite) ->
- [];
-ip_mod_all(Config) when is_list(Config) ->
- httpd_mod:all(ip_comm, ?IP_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_load_light(doc) ->
- ["Test light load"];
-ip_load_light(suite) ->
- [];
-ip_load_light(Config) when is_list(Config) ->
- httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config),
- get_nof_clients(ip_comm, light)),
- ok.
-%%-------------------------------------------------------------------------
-ip_load_medium(doc) ->
- ["Test medium load"];
-ip_load_medium(suite) ->
- [];
-ip_load_medium(Config) when is_list(Config) ->
- httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config),
- get_nof_clients(ip_comm, medium)),
- ok.
-%%-------------------------------------------------------------------------
-ip_load_heavy(doc) ->
- ["Test heavy load"];
-ip_load_heavy(suite) ->
- [];
-ip_load_heavy(Config) when is_list(Config) ->
- httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config),
- get_nof_clients(ip_comm, heavy)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ip_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case"];
-ip_dos_hostname(suite) ->
- [];
-ip_dos_hostname(Config) when is_list(Config) ->
- dos_hostname(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config), ?MAX_HEADER_SIZE),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ip_time_test(doc) ->
- [""];
-ip_time_test(suite) ->
- [];
-ip_time_test(Config) when is_list(Config) ->
- %% <CONDITIONAL-SKIP>
- Skippable = [win32],
- Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_time_test:t(ip_comm, ?config(host, Config), ?IP_PORT),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked."];
-ip_block_503(suite) ->
- [];
-ip_block_503(Config) when is_list(Config) ->
- httpd_block:block_503(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."];
-ip_block_disturbing_idle(suite) ->
- [];
-ip_block_disturbing_idle(Config) when is_list(Config) ->
- httpd_block:block_disturbing_idle(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."];
-ip_block_non_disturbing_idle(suite) ->
- [];
-ip_block_non_disturbing_idle(Config) when is_list(Config) ->
- httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."];
-ip_block_disturbing_active(suite) ->
- [];
-ip_block_disturbing_active(Config) when is_list(Config) ->
- httpd_block:block_disturbing_active(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."];
-ip_block_non_disturbing_active(suite) ->
- [];
-ip_block_non_disturbing_active(Config) when is_list(Config) ->
- httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."];
-ip_block_disturbing_active_timeout_not_released(suite) ->
- [];
-ip_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- httpd_block:block_disturbing_active_timeout_not_released(ip_comm,
- ?IP_PORT,
- ?config(host,
- Config),
- ?config(node,
- Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."];
-ip_block_disturbing_active_timeout_released(suite) ->
- [];
-ip_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- httpd_block:block_disturbing_active_timeout_released(ip_comm,
- ?IP_PORT,
- ?config(host,
- Config),
- ?config(node,
- Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."];
-ip_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-ip_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- httpd_block:
- block_non_disturbing_active_timeout_not_released(ip_comm,
- ?IP_PORT,
- ?config(host,
- Config),
- ?config(node,
- Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled." ];
-ip_block_non_disturbing_active_timeout_released(suite) ->
- [];
-ip_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- httpd_block:
- block_non_disturbing_active_timeout_released(ip_comm,
- ?IP_PORT,
- ?config(host,
- Config),
- ?config(node,
- Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_disturbing_blocker_dies(doc) ->
- [];
-ip_block_disturbing_blocker_dies(suite) ->
- [];
-ip_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- httpd_block:disturbing_blocker_dies(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_block_non_disturbing_blocker_dies(doc) ->
- [];
-ip_block_non_disturbing_blocker_dies(suite) ->
- [];
-ip_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- httpd_block:non_disturbing_blocker_dies(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_restart_no_block(doc) ->
- [""];
-ip_restart_no_block(suite) ->
- [];
-ip_restart_no_block(Config) when is_list(Config) ->
- httpd_block:restart_no_block(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_restart_disturbing_block(doc) ->
- [""];
-ip_restart_disturbing_block(suite) ->
- [];
-ip_restart_disturbing_block(Config) when is_list(Config) ->
- %% <CONDITIONAL-SKIP>
- Condition =
- fun() ->
- case os:type() of
- {unix, linux} ->
- HW = string:strip(os:cmd("uname -m"), right, $\n),
- case HW of
- "ppc" ->
- case inet:gethostname() of
- {ok, "peach"} ->
- true;
- _ ->
- false
- end;
- _ ->
- false
- end;
- _ ->
- false
- end
- end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_block:restart_disturbing_block(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_restart_non_disturbing_block(doc) ->
- [""];
-ip_restart_non_disturbing_block(suite) ->
- [];
-ip_restart_non_disturbing_block(Config) when is_list(Config) ->
- %% <CONDITIONAL-SKIP>
- Condition =
- fun() ->
- case os:type() of
- {unix, linux} ->
- HW = string:strip(os:cmd("uname -m"), right, $\n),
- case HW of
- "ppc" ->
- case inet:gethostname() of
- {ok, "peach"} ->
- true;
- _ ->
- false
- end;
- _ ->
- false
- end;
- _ ->
- false
- end
- end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_block:restart_non_disturbing_block(ip_comm, ?IP_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_alias(doc) ->
- ["Module test: mod_alias - old SSL config"];
-pssl_mod_alias(suite) ->
- [];
-pssl_mod_alias(Config) when is_list(Config) ->
- ssl_mod_alias(ssl, Config).
-
-essl_mod_alias(doc) ->
- ["Module test: mod_alias - using new of configure new SSL"];
-essl_mod_alias(suite) ->
- [];
-essl_mod_alias(Config) when is_list(Config) ->
- ssl_mod_alias(essl, Config).
-
-
-ssl_mod_alias(Tag, Config) ->
- httpd_mod:alias(Tag, ?SSL_PORT,
- ?config(host, Config), ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_actions(doc) ->
- ["Module test: mod_actions - old SSL config"];
-pssl_mod_actions(suite) ->
- [];
-pssl_mod_actions(Config) when is_list(Config) ->
- ssl_mod_actions(ssl, Config).
-
-essl_mod_actions(doc) ->
- ["Module test: mod_actions - using new of configure new SSL"];
-essl_mod_actions(suite) ->
- [];
-essl_mod_actions(Config) when is_list(Config) ->
- ssl_mod_actions(essl, Config).
-
-
-ssl_mod_actions(Tag, Config) ->
- httpd_mod:actions(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_security(doc) ->
- ["Module test: mod_security - old SSL config"];
-pssl_mod_security(suite) ->
- [];
-pssl_mod_security(Config) when is_list(Config) ->
- ssl_mod_security(ssl, Config).
-
-essl_mod_security(doc) ->
- ["Module test: mod_security - using new of configure new SSL"];
-essl_mod_security(suite) ->
- [];
-essl_mod_security(Config) when is_list(Config) ->
- ssl_mod_security(essl, Config).
-
-ssl_mod_security(Tag, Config) ->
- ServerRoot = ?config(server_root, Config),
- httpd_mod:security(ServerRoot,
- Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_auth(doc) ->
- ["Module test: mod_auth - old SSL config"];
-pssl_mod_auth(suite) ->
- [];
-pssl_mod_auth(Config) when is_list(Config) ->
- ssl_mod_auth(ssl, Config).
-
-essl_mod_auth(doc) ->
- ["Module test: mod_auth - using new of configure new SSL"];
-essl_mod_auth(suite) ->
- [];
-essl_mod_auth(Config) when is_list(Config) ->
- ssl_mod_auth(essl, Config).
-
-ssl_mod_auth(Tag, Config) ->
- httpd_mod:auth(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_auth_api(doc) ->
- ["Module test: mod_auth - old SSL config"];
-pssl_mod_auth_api(suite) ->
- [];
-pssl_mod_auth_api(Config) when is_list(Config) ->
- ssl_mod_auth_api(ssl, Config).
-
-essl_mod_auth_api(doc) ->
- ["Module test: mod_auth - using new of configure new SSL"];
-essl_mod_auth_api(suite) ->
- [];
-essl_mod_auth_api(Config) when is_list(Config) ->
- ssl_mod_auth_api(essl, Config).
-
-ssl_mod_auth_api(Tag, Config) ->
- ServerRoot = ?config(server_root, Config),
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- httpd_mod:auth_api(ServerRoot, "", Tag, ?SSL_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "dets_", Tag, ?SSL_PORT, Host, Node),
- httpd_mod:auth_api(ServerRoot, "mnesia_", Tag, ?SSL_PORT, Host, Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api - old SSL config"];
-pssl_mod_auth_mnesia_api(suite) ->
- [];
-pssl_mod_auth_mnesia_api(Config) when is_list(Config) ->
- ssl_mod_auth_mnesia_api(ssl, Config).
-
-essl_mod_auth_mnesia_api(doc) ->
- ["Module test: mod_auth_mnesia_api - using new of configure new SSL"];
-essl_mod_auth_mnesia_api(suite) ->
- [];
-essl_mod_auth_mnesia_api(Config) when is_list(Config) ->
- ssl_mod_auth_mnesia_api(essl, Config).
-
-ssl_mod_auth_mnesia_api(Tag, Config) ->
- httpd_mod:auth_mnesia_api(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_htaccess(doc) ->
- ["Module test: mod_htaccess - old SSL config"];
-pssl_mod_htaccess(suite) ->
- [];
-pssl_mod_htaccess(Config) when is_list(Config) ->
- ssl_mod_htaccess(ssl, Config).
-
-essl_mod_htaccess(doc) ->
- ["Module test: mod_htaccess - using new of configure new SSL"];
-essl_mod_htaccess(suite) ->
- [];
-essl_mod_htaccess(Config) when is_list(Config) ->
- ssl_mod_htaccess(essl, Config).
-
-ssl_mod_htaccess(Tag, Config) ->
- httpd_mod:htaccess(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_cgi(doc) ->
- ["Module test: mod_cgi - old SSL config"];
-pssl_mod_cgi(suite) ->
- [];
-pssl_mod_cgi(Config) when is_list(Config) ->
- ssl_mod_cgi(ssl, Config).
-
-essl_mod_cgi(doc) ->
- ["Module test: mod_cgi - using new of configure new SSL"];
-essl_mod_cgi(suite) ->
- [];
-essl_mod_cgi(Config) when is_list(Config) ->
- ssl_mod_cgi(essl, Config).
-
-ssl_mod_cgi(Tag, Config) ->
- case test_server:os_type() of
- vxworks ->
- {skip, cgi_not_supported_on_vxwoks};
- _ ->
- httpd_mod:cgi(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok
- end.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_esi(doc) ->
- ["Module test: mod_esi - old SSL config"];
-pssl_mod_esi(suite) ->
- [];
-pssl_mod_esi(Config) when is_list(Config) ->
- ssl_mod_esi(ssl, Config).
-
-essl_mod_esi(doc) ->
- ["Module test: mod_esi - using new of configure new SSL"];
-essl_mod_esi(suite) ->
- [];
-essl_mod_esi(Config) when is_list(Config) ->
- ssl_mod_esi(essl, Config).
-
-ssl_mod_esi(Tag, Config) ->
- httpd_mod:esi(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_get(doc) ->
- ["Module test: mod_get - old SSL config"];
-pssl_mod_get(suite) ->
- [];
-pssl_mod_get(Config) when is_list(Config) ->
- ssl_mod_get(ssl, Config).
-
-essl_mod_get(doc) ->
- ["Module test: mod_get - using new of configure new SSL"];
-essl_mod_get(suite) ->
- [];
-essl_mod_get(Config) when is_list(Config) ->
- ssl_mod_get(essl, Config).
-
-ssl_mod_get(Tag, Config) ->
- httpd_mod:get(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_head(doc) ->
- ["Module test: mod_head - old SSL config"];
-pssl_mod_head(suite) ->
- [];
-pssl_mod_head(Config) when is_list(Config) ->
- ssl_mod_head(ssl, Config).
-
-essl_mod_head(doc) ->
- ["Module test: mod_head - using new of configure new SSL"];
-essl_mod_head(suite) ->
- [];
-essl_mod_head(Config) when is_list(Config) ->
- ssl_mod_head(essl, Config).
-
-ssl_mod_head(Tag, Config) ->
- httpd_mod:head(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_mod_all(doc) ->
- ["All modules test - old SSL config"];
-pssl_mod_all(suite) ->
- [];
-pssl_mod_all(Config) when is_list(Config) ->
- ssl_mod_all(ssl, Config).
-
-essl_mod_all(doc) ->
- ["All modules test - using new of configure new SSL"];
-essl_mod_all(suite) ->
- [];
-essl_mod_all(Config) when is_list(Config) ->
- ssl_mod_all(essl, Config).
-
-ssl_mod_all(Tag, Config) ->
- httpd_mod:all(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_load_light(doc) ->
- ["Test light load - old SSL config"];
-pssl_load_light(suite) ->
- [];
-pssl_load_light(Config) when is_list(Config) ->
- ssl_load_light(ssl, Config).
-
-essl_load_light(doc) ->
- ["Test light load - using new of configure new SSL"];
-essl_load_light(suite) ->
- [];
-essl_load_light(Config) when is_list(Config) ->
- ssl_load_light(essl, Config).
-
-ssl_load_light(Tag, Config) ->
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config),
- get_nof_clients(ssl, light)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_load_medium(doc) ->
- ["Test medium load - old SSL config"];
-pssl_load_medium(suite) ->
- [];
-pssl_load_medium(Config) when is_list(Config) ->
- ssl_load_medium(ssl, Config).
-
-essl_load_medium(doc) ->
- ["Test medium load - using new of configure new SSL"];
-essl_load_medium(suite) ->
- [];
-essl_load_medium(Config) when is_list(Config) ->
- ssl_load_medium(essl, Config).
-
-ssl_load_medium(Tag, Config) ->
- %% <CONDITIONAL-SKIP>
- Skippable = [win32],
- Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config),
- get_nof_clients(ssl, medium)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_load_heavy(doc) ->
- ["Test heavy load - old SSL config"];
-pssl_load_heavy(suite) ->
- [];
-pssl_load_heavy(Config) when is_list(Config) ->
- ssl_load_heavy(ssl, Config).
-
-essl_load_heavy(doc) ->
- ["Test heavy load - using new of configure new SSL"];
-essl_load_heavy(suite) ->
- [];
-essl_load_heavy(Config) when is_list(Config) ->
- ssl_load_heavy(essl, Config).
-
-ssl_load_heavy(Tag, Config) ->
- %% <CONDITIONAL-SKIP>
- Skippable = [win32],
- Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config),
- get_nof_clients(ssl, heavy)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case - old SSL config"];
-pssl_dos_hostname(suite) ->
- [];
-pssl_dos_hostname(Config) when is_list(Config) ->
- ssl_dos_hostname(ssl, Config).
-
-essl_dos_hostname(doc) ->
- ["Denial Of Service (DOS) attack test case - using new of configure new SSL"];
-essl_dos_hostname(suite) ->
- [];
-essl_dos_hostname(Config) when is_list(Config) ->
- ssl_dos_hostname(essl, Config).
-
-ssl_dos_hostname(Tag, Config) ->
- dos_hostname(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config),
- ?MAX_HEADER_SIZE),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_time_test(doc) ->
- ["old SSL config"];
-pssl_time_test(suite) ->
- [];
-pssl_time_test(Config) when is_list(Config) ->
- ssl_time_test(ssl, Config).
-
-essl_time_test(doc) ->
- ["using new of configure new SSL"];
-essl_time_test(suite) ->
- [];
-essl_time_test(Config) when is_list(Config) ->
- ssl_time_test(essl, Config).
-
-ssl_time_test(Tag, Config) when is_list(Config) ->
- %% <CONDITIONAL-SKIP>
- FreeBSDVersionVerify =
- fun() ->
- case os:version() of
- {7, 1, _} -> % We only have one such machine, so...
- true;
- _ ->
- false
- end
- end,
- Skippable = [win32, {unix, [{freebsd, FreeBSDVersionVerify}]}],
- Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_time_test:t(Tag,
- ?config(host, Config),
- ?SSL_PORT),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked - old SSL config."];
-pssl_block_503(suite) ->
- [];
-pssl_block_503(Config) when is_list(Config) ->
- ssl_block_503(ssl, Config).
-
-essl_block_503(doc) ->
- ["Check that you will receive status code 503 when the server"
- " is blocked and 200 when its not blocked - using new of configure new SSL."];
-essl_block_503(suite) ->
- [];
-essl_block_503(Config) when is_list(Config) ->
- ssl_block_503(essl, Config).
-
-ssl_block_503(Tag, Config) ->
- httpd_block:block_503(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."
- "Old SSL config"];
-pssl_block_disturbing_idle(suite) ->
- [];
-pssl_block_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_disturbing_idle(ssl, Config).
-
-essl_block_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "distribing does not really make a difference in this case."
- "Using new of configure new SSL"];
-essl_block_disturbing_idle(suite) ->
- [];
-essl_block_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_disturbing_idle(essl, Config).
-
-ssl_block_disturbing_idle(Tag, Config) ->
- httpd_block:block_disturbing_idle(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."
- "Old SSL config"];
-pssl_block_non_disturbing_idle(suite) ->
- [];
-pssl_block_non_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_non_disturbing_idle(ssl, Config).
-
-essl_block_non_disturbing_idle(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing does not really make a difference in this case."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_idle(suite) ->
- [];
-essl_block_non_disturbing_idle(Config) when is_list(Config) ->
- ssl_block_non_disturbing_idle(essl, Config).
-
-ssl_block_non_disturbing_idle(Tag, Config) ->
- httpd_block:block_non_disturbing_idle(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."
- "Old SSL config"];
-pssl_block_disturbing_active(suite) ->
- [];
-pssl_block_disturbing_active(Config) when is_list(Config) ->
- ssl_block_disturbing_active(ssl, Config).
-
-essl_block_disturbing_active(doc) ->
- ["Check that you can block/unblock an active server. The strategy "
- "distribing means ongoing requests should be terminated."
- "Using new of configure new SSL"];
-essl_block_disturbing_active(suite) ->
- [];
-essl_block_disturbing_active(Config) when is_list(Config) ->
- ssl_block_disturbing_active(essl, Config).
-
-ssl_block_disturbing_active(Tag, Config) ->
- httpd_block:block_disturbing_active(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."
- "Old SSL config"];
-pssl_block_non_disturbing_active(suite) ->
- [];
-pssl_block_non_disturbing_active(Config) when is_list(Config) ->
- ssl_block_non_disturbing_active(ssl, Config).
-
-essl_block_non_disturbing_active(doc) ->
- ["Check that you can block/unblock an idle server. The strategy "
- "non distribing means the ongoing requests should be compleated."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_active(suite) ->
- [];
-essl_block_non_disturbing_active(Config) when is_list(Config) ->
- ssl_block_non_disturbing_active(essl, Config).
-
-ssl_block_non_disturbing_active(Tag, Config) ->
- httpd_block:block_non_disturbing_idle(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."
- "Old SSL config"];
-pssl_block_disturbing_active_timeout_not_released(suite) ->
- [];
-pssl_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_not_released(ssl, Config).
-
-essl_block_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be compleated"
- "if the timeout does not occur."
- "Using new of configure new SSL"];
-essl_block_disturbing_active_timeout_not_released(suite) ->
- [];
-essl_block_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_not_released(essl, Config).
-
-ssl_block_disturbing_active_timeout_not_released(Tag, Config) ->
- Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- httpd_block:block_disturbing_active_timeout_not_released(Tag,
- Port, Host, Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."
- "Old SSL config"];
-pssl_block_disturbing_active_timeout_released(suite) ->
- [];
-pssl_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_released(ssl, Config).
-
-essl_block_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "distribing means ongoing requests should be terminated when"
- "the timeout occurs."
- "Using new of configure new SSL"];
-essl_block_disturbing_active_timeout_released(suite) ->
- [];
-essl_block_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_disturbing_active_timeout_released(essl, Config).
-
-ssl_block_disturbing_active_timeout_released(Tag, Config) ->
- Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- httpd_block:block_disturbing_active_timeout_released(Tag,
- Port,
- Host,
- Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."
- "Old SSL config"];
-pssl_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-pssl_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_not_released(ssl, Config).
-
-essl_block_non_disturbing_active_timeout_not_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non non distribing means ongoing requests should be completed."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_active_timeout_not_released(suite) ->
- [];
-essl_block_non_disturbing_active_timeout_not_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_not_released(essl, Config).
-
-ssl_block_non_disturbing_active_timeout_not_released(Tag, Config) ->
- Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- httpd_block:block_non_disturbing_active_timeout_not_released(Tag,
- Port,
- Host,
- Node),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled."
- "Old SSL config"];
-pssl_block_non_disturbing_active_timeout_released(suite) ->
- [];
-pssl_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_released(ssl, Config).
-
-essl_block_non_disturbing_active_timeout_released(doc) ->
- ["Check that you can block an active server. The strategy "
- "non distribing means ongoing requests should be completed. "
- "When the timeout occurs the block operation sohould be canceled."
- "Using new of configure new SSL"];
-essl_block_non_disturbing_active_timeout_released(suite) ->
- [];
-essl_block_non_disturbing_active_timeout_released(Config)
- when is_list(Config) ->
- ssl_block_non_disturbing_active_timeout_released(essl, Config).
-
-ssl_block_non_disturbing_active_timeout_released(Tag, Config)
- when is_list(Config) ->
- Port = ?SSL_PORT,
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- httpd_block:block_non_disturbing_active_timeout_released(Tag,
- Port,
- Host,
- Node),
-
- ok.
-
+init_per_testcase(host, Config) ->
+ Prop = ?config(tc_group_properties, Config),
+ Name = proplists:get_value(name, Prop),
+ Cb = case Name of
+ http_1_0 ->
+ httpd_1_0;
+ http_1_1 ->
+ httpd_1_1
+ end,
+ [{version_cb, Cb} | proplists:delete(version_cb, Config)];
+init_per_testcase(_, Config) ->
+ Config.
-%%-------------------------------------------------------------------------
+%% init_per_testcase(basic_auth = Case, Config) ->
+%% start_mnesia(?config(node, Config)),
+%% common_init_per_test_case(Case, Config);
-pssl_block_disturbing_blocker_dies(doc) ->
- ["old SSL config"];
-pssl_block_disturbing_blocker_dies(suite) ->
- [];
-pssl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_disturbing_blocker_dies(ssl, Config).
-
-essl_block_disturbing_blocker_dies(doc) ->
- ["using new of configure new SSL"];
-essl_block_disturbing_blocker_dies(suite) ->
- [];
-essl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_disturbing_blocker_dies(essl, Config).
-
-ssl_block_disturbing_blocker_dies(Tag, Config) ->
- httpd_block:disturbing_blocker_dies(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
+%% end_per_testcase(basic_auth, Config) ->
+%% cleanup_mnesia();
+end_per_testcase(_Case, _Config) ->
ok.
-
%%-------------------------------------------------------------------------
-
-pssl_block_non_disturbing_blocker_dies(doc) ->
- ["old SSL config"];
-pssl_block_non_disturbing_blocker_dies(suite) ->
- [];
-pssl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_non_disturbing_blocker_dies(ssl, Config).
-
-essl_block_non_disturbing_blocker_dies(doc) ->
- ["using new of configure new SSL"];
-essl_block_non_disturbing_blocker_dies(suite) ->
- [];
-essl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
- ssl_block_non_disturbing_blocker_dies(essl, Config).
-
-ssl_block_non_disturbing_blocker_dies(Tag, Config) ->
- httpd_block:non_disturbing_blocker_dies(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-pssl_restart_no_block(doc) ->
- ["old SSL config"];
-pssl_restart_no_block(suite) ->
- [];
-pssl_restart_no_block(Config) when is_list(Config) ->
- ssl_restart_no_block(ssl, Config).
-
-essl_restart_no_block(doc) ->
- ["using new of configure new SSL"];
-essl_restart_no_block(suite) ->
- [];
-essl_restart_no_block(Config) when is_list(Config) ->
- ssl_restart_no_block(essl, Config).
-
-ssl_restart_no_block(Tag, Config) ->
- httpd_block:restart_no_block(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
+%% Test cases starts here.
%%-------------------------------------------------------------------------
-pssl_restart_disturbing_block(doc) ->
- ["old SSL config"];
-pssl_restart_disturbing_block(suite) ->
- [];
-pssl_restart_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_disturbing_block(ssl, Config).
-
-essl_restart_disturbing_block(doc) ->
- ["using new of configure new SSL"];
-essl_restart_disturbing_block(suite) ->
- [];
-essl_restart_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_disturbing_block(essl, Config).
-
-ssl_restart_disturbing_block(Tag, Config) ->
- %% <CONDITIONAL-SKIP>
- Condition =
- fun() ->
- case os:type() of
- {unix, linux} ->
- case ?OSCMD("uname -m") of
- "ppc" ->
- case file:read_file_info("/etc/fedora-release") of
- {ok, _} ->
- case ?OSCMD("awk '{print $2}' /etc/fedora-release") of
- "release" ->
- %% Fedora 7 and later
- case ?OSCMD("awk '{print $3}' /etc/fedora-release") of
- "7" ->
- true;
- _ ->
- false
- end;
- _ ->
- false
- end;
- _ ->
- false
- end;
- _ ->
- false
- end;
- _ ->
- false
- end
- end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
-
- httpd_block:restart_disturbing_block(Tag, ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
-
-
-%%-------------------------------------------------------------------------
+head() ->
+ [{doc, "HTTP HEAD request for static page"}].
-pssl_restart_non_disturbing_block(doc) ->
- ["old SSL config"];
-pssl_restart_non_disturbing_block(suite) ->
- [];
-pssl_restart_non_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_non_disturbing_block(ssl, Config).
-
-essl_restart_non_disturbing_block(doc) ->
- ["using new of configure new SSL"];
-essl_restart_non_disturbing_block(suite) ->
- [];
-essl_restart_non_disturbing_block(Config) when is_list(Config) ->
- ssl_restart_non_disturbing_block(essl, Config).
-
-ssl_restart_non_disturbing_block(Tag, Config) ->
- %% <CONDITIONAL-SKIP>
- Condition =
- fun() ->
- case os:type() of
- {unix, linux} ->
- HW = string:strip(os:cmd("uname -m"), right, $\n),
- case HW of
- "ppc" ->
- case inet:gethostname() of
- {ok, "peach"} ->
- true;
- _ ->
- false
- end;
- _ ->
- false
- end;
- _ ->
- false
- end
- end,
- ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
- %% </CONDITIONAL-SKIP>
+head(Config) when is_list(Config) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request("HEAD /index.html ", Version, Host),
+ [{statuscode, head_status(Version)},
+ {version, Version}]).
- httpd_block:restart_non_disturbing_block(Tag,
- ?SSL_PORT,
- ?config(host, Config),
- ?config(node, Config)),
- ok.
+get() ->
+ [{doc, "HTTP GET request for static page"}].
+get(Config) when is_list(Config) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request("GET /index.html ", Version, Host),
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
+ {version, Version}]).
-%%-------------------------------------------------------------------------
-ip_host(doc) ->
- ["Control that the server accepts/rejects requests with/ without host"];
-ip_host(suite)->
- [];
-ip_host(Config) when is_list(Config) ->
- httpd_1_1:host(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_chunked(doc) ->
- ["Control that the server accepts chunked requests"];
-ip_chunked(suite) ->
- [];
-ip_chunked(Config) when is_list(Config) ->
- httpd_1_1:chunked(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_expect(doc) ->
- ["Control that the server handles request with the expect header "
- "field appropiate"];
-ip_expect(suite)->
- [];
-ip_expect(Config) when is_list(Config) ->
- httpd_1_1:expect(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_range(doc) ->
- ["Control that the server can handle range requests to plain files"];
-ip_range(suite)->
- [];
-ip_range(Config) when is_list(Config) ->
- httpd_1_1:range(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_if_test(doc) ->
- ["Test that the if - request header fields is handled correclty"];
-ip_if_test(suite) ->
- [];
-ip_if_test(Config) when is_list(Config) ->
- ServerRoot = ?config(server_root, Config),
- DocRoot = filename:join([ServerRoot, "htdocs"]),
- httpd_1_1:if_test(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config), DocRoot),
- ok.
-%%-------------------------------------------------------------------------
-ip_http_trace(doc) ->
- ["Test the trace module "];
-ip_http_trace(suite) ->
- [];
-ip_http_trace(Config) when is_list(Config) ->
- httpd_1_1:http_trace(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_http1_1_head(doc) ->
- ["Test the trace module "];
-ip_http1_1_head(suite)->
- [];
-ip_http1_1_head(Config) when is_list(Config) ->
- httpd_1_1:head(ip_comm, ?IP_PORT, ?config(host, Config),
- ?config(node, Config)),
- ok.
+basic_auth() ->
+ [{doc, "Test Basic authentication with WWW-Authenticate header"}].
-%%-------------------------------------------------------------------------
-ip_get_0_9(doc) ->
- ["Test simple HTTP/0.9 GET"];
-ip_get_0_9(suite)->
- [];
-ip_get_0_9(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET / \r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/0.9"} ]),
- %% Without space after uri
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET /\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/0.9"} ]),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET / HTTP/0.9\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/0.9"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_head_1_0(doc) ->
- ["Test HTTP/1.0 HEAD"];
-ip_head_1_0(suite)->
- [];
-ip_head_1_0(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "HEAD / HTTP/1.0\r\n\r\n", [{statuscode, 200},
- {version, "HTTP/1.0"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_get_1_0(doc) ->
- ["Test HTTP/1.0 GET"];
-ip_get_1_0(suite)->
- [];
-ip_get_1_0(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "GET / HTTP/1.0\r\n\r\n", [{statuscode, 200},
- {version, "HTTP/1.0"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_post_1_0(doc) ->
- ["Test HTTP/1.0 POST"];
-ip_post_1_0(suite)->
- [];
-ip_post_1_0(Config) when is_list(Config) ->
- Host = ?config(host, Config),
- Node = ?config(node, Config),
- %% Test the post message formatin 1.0! Real post are testes elsewhere
- ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
- "POST / HTTP/1.0\r\n\r\n "
- "Content-Length:6 \r\n\r\nfoobar",
- [{statuscode, 500}, {version, "HTTP/1.0"}]),
-
- ok.
-%%-------------------------------------------------------------------------
-ip_mod_cgi_chunked_encoding_test(doc) ->
- ["Test the trace module "];
-ip_mod_cgi_chunked_encoding_test(suite)->
- [];
-ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) ->
+basic_auth(Config) ->
+ Version = ?config(http_version, Config),
Host = ?config(host, Config),
- Script =
+ basic_auth_requiered(Config),
+ %% Authentication OK! ["one:OnePassword" user first in user list]
+ ok = auth_status(auth_request("/open/dummy.html", "one", "onePassword", Version, Host), Config,
+ [{statuscode, 200}]),
+ %% Authentication OK and a directory listing is supplied!
+ %% ["Aladdin:open sesame" user second in user list]
+ ok = auth_status(auth_request("/open/", "Aladdin", "AladdinPassword", Version, Host), Config,
+ [{statuscode, 200}]),
+ %% User correct but wrong password! ["one:one" user first in user list]
+ ok = auth_status(auth_request("/open/dummy.html", "one", "one", Version, Host), Config,
+ [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+ %% Make sure Authenticate header is received even the second time
+ %% we try a incorrect password! Otherwise a browser client will hang!
+ ok = auth_status(auth_request("/open/dummy.html", "one", "one", Version, Host), Config,
+ [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+ %% Neither user or password correct! ["dummy:dummy"]
+ ok = auth_status(auth_request("/open/dummy.html", "dummy", "dummy", Version, Host), Config,
+ [{statuscode, 401}]),
+ %% Nested secret/top_secret OK! ["Aladdin:open sesame"]
+ ok = http_status(auth_request("/secret/top_secret/", "Aladdin", "AladdinPassword", Version, Host),
+ Config, [{statuscode, 200}]),
+ %% Authentication still required!
+ basic_auth_requiered(Config).
+
+ssi() ->
+ [{doc, "HTTP GET server side include test"}].
+ssi(Config) when is_list(Config) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host, ?config(port, Config),
+ ?config(node, Config),
+ http_request("GET /fsize.shtml ", Version, Host),
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
+ {version, Version}]).
+host() ->
+ [{doc, "Test host header"}].
+
+host(Config) when is_list(Config) ->
+ Cb = ?config(version_cb, Config),
+ Cb:host(?config(type, Config), ?config(port, Config),
+ ?config(host, Config), ?config(node, Config)).
+
+chunked() ->
+ [{doc, "Check that the server accepts chunked requests."}].
+
+chunked(Config) when is_list(Config) ->
+ httpd_1_1:chunked(?config(type, Config), ?config(port, Config),
+ ?config(host, Config), ?config(node, Config)).
+
+expect() ->
+ ["Check that the server handles request with the expect header "
+ "field appropiate"].
+expect(Config) when is_list(Config) ->
+ httpd_1_1:expect(?config(type, Config), ?config(port, Config),
+ ?config(host, Config), ?config(node, Config)).
+
+max_clients_1_1() ->
+ [{doc, "Test max clients limit"}].
+
+
+max_clients_1_1(Config) when is_list(Config) ->
+ do_max_clients([{http_version, "HTTP/1.1"} | Config]).
+
+max_clients_1_0() ->
+ [{doc, "Test max clients limit"}].
+
+max_clients_1_0(Config) when is_list(Config) ->
+ do_max_clients([{http_version, "HTTP/1.0"} | Config]).
+
+max_clients_0_9() ->
+ [{doc, "Test max clients limit"}].
+
+max_clients_0_9(Config) when is_list(Config) ->
+ do_max_clients([{http_version, "HTTP/0.9"} | Config]).
+
+esi() ->
+ [{doc, "Test mod_esi"}].
+
+esi(Config) when is_list(Config) ->
+ ok = http_status("GET /eval?httpd_example:print(\"Hi!\") ",
+ Config, [{statuscode, 200}]),
+ ok = http_status("GET /eval?not_allowed:print(\"Hi!\") ",
+ Config, [{statuscode, 403}]),
+ ok = http_status("GET /eval?httpd_example:undef(\"Hi!\") ",
+ Config, [{statuscode, 500}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example ",
+ Config, [{statuscode, 400}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example:get ",
+ Config, [{statuscode, 200}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example:"
+ "get?input=4711 ", Config,
+ [{statuscode, 200}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example:post ",
+ Config, [{statuscode, 200}]),
+ ok = http_status("GET /cgi-bin/erl/not_allowed:post ",
+ Config, [{statuscode, 403}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example:undef ",
+ Config, [{statuscode, 404}]),
+ ok = http_status("GET /cgi-bin/erl/httpd_example/yahoo ",
+ Config, [{statuscode, 302}]),
+ %% Check "ErlScriptNoCache" directive (default: false)
+ ok = http_status("GET /cgi-bin/erl/httpd_example:get ",
+ Config, [{statuscode, 200},
+ {no_header, "cache-control"}]).
+
+cgi() ->
+ [{doc, "Test mod_cgi"}].
+
+cgi(Config) when is_list(Config) ->
+ {Script, Script2, Script3} =
case test_server:os_type() of
{win32, _} ->
- "/cgi-bin/printenv.bat";
+ {"printenv.bat", "printenv.sh", "cgi_echo.exe"};
_ ->
- "/cgi-bin/printenv.sh"
+ {"printenv.sh", "printenv.bat", "cgi_echo"}
end,
- Requests =
- ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n",
- "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:"
- ++ Host ++"\r\n\r\n"],
- httpd_1_1:mod_cgi_chunked_encoding_test(ip_comm, ?IP_PORT,
- Host,
- ?config(node, Config),
- Requests),
- ok.
-%-------------------------------------------------------------------------
-
-ipv6_hostname_ipcomm() ->
- [{require, ipv6_hosts}].
-ipv6_hostname_ipcomm(X) ->
- SocketType = ip_comm,
- Port = ?IP_PORT,
- ipv6_hostname(SocketType, Port, X).
-
-ipv6_hostname_essl() ->
- [{require, ipv6_hosts}].
-ipv6_hostname_essl(X) ->
- SocketType = essl,
- Port = ?SSL_PORT,
- ipv6_hostname(SocketType, Port, X).
-
-ipv6_hostname(_SocketType, _Port, doc) ->
- ["Test standard ipv6 address"];
-ipv6_hostname(_SocketType, _Port, suite)->
- [];
-ipv6_hostname(SocketType, Port, Config) when is_list(Config) ->
- tsp("ipv6_hostname -> entry with"
- "~n SocketType: ~p"
- "~n Port: ~p"
- "~n Config: ~p", [SocketType, Port, Config]),
- Host = ?config(host, Config),
- URI = "GET HTTP://" ++
- Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
- tsp("ipv6_hostname -> Host: ~p", [Host]),
- httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
- node(),
- URI,
- [{statuscode, 200}, {version, "HTTP/1.1"}]),
- ok.
-
-%%-------------------------------------------------------------------------
-
-ipv6_address_ipcomm() ->
- [{require, ipv6_hosts}].
-ipv6_address_ipcomm(X) ->
- SocketType = ip_comm,
- Port = ?IP_PORT,
- ipv6_address(SocketType, Port, X).
-
-ipv6_address_essl() ->
- [{require, ipv6_hosts}].
-ipv6_address_essl(X) ->
- SocketType = essl,
- Port = ?SSL_PORT,
- ipv6_address(SocketType, Port, X).
-
-ipv6_address(_SocketType, _Port, doc) ->
- ["Test standard ipv6 address"];
-ipv6_address(_SocketType, _Port, suite)->
- [];
-ipv6_address(SocketType, Port, Config) when is_list(Config) ->
- tsp("ipv6_address -> entry with"
- "~n SocketType: ~p"
- "~n Port: ~p"
- "~n Config: ~p", [SocketType, Port, Config]),
- Host = ?config(host, Config),
- tsp("ipv6_address -> Host: ~p", [Host]),
- URI = "GET HTTP://" ++
- Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
- httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
- node(),
- URI,
- [{statuscode, 200}, {version, "HTTP/1.1"}]),
- ok.
+ %%The length (> 100) is intentional
+ ok = http_status("POST /cgi-bin/" ++ Script3 ++ " ",
+ {"Content-Length:100 \r\n",
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"},
+ Config,
+ [{statuscode, 200},
+ {header, "content-type", "text/plain"}]),
+
+ ok = http_status("GET /cgi-bin/"++ Script ++ " ", Config, [{statuscode, 200}]),
+
+ ok = http_status("GET /cgi-bin/not_there ", Config,
+ [{statuscode, 404}, {statuscode, 500}]),
+
+ ok = http_status("GET /cgi-bin/"++ Script ++ "?Nisse:kkk?sss/lll ",
+ Config,
+ [{statuscode, 200}]),
+
+ ok = http_status("POST /cgi-bin/"++ Script ++ " ", Config,
+ [{statuscode, 200}]),
+
+ ok = http_status("GET /htbin/"++ Script ++ " ", Config,
+ [{statuscode, 200}]),
+
+ ok = http_status("GET /htbin/not_there ", Config,
+ [{statuscode, 404},{statuscode, 500}]),
+
+ ok = http_status("GET /htbin/"++ Script ++ "?Nisse:kkk?sss/lll ", Config,
+ [{statuscode, 200}]),
+
+ ok = http_status("POST /htbin/"++ Script ++ " ", Config,
+ [{statuscode, 200}]),
+
+ ok = http_status("POST /htbin/"++ Script ++ " ", Config,
+ [{statuscode, 200}]),
+
+ %% Execute an existing, but bad CGI script..
+ ok = http_status("POST /htbin/"++ Script2 ++ " ", Config,
+ [{statuscode, 404}]),
+
+ ok = http_status("POST /cgi-bin/"++ Script2 ++ " ", Config,
+ [{statuscode, 404}]),
+
+ %% Check "ScriptNoCache" directive (default: false)
+ ok = http_status("GET /cgi-bin/" ++ Script ++ " ", Config,
+ [{statuscode, 200},
+ {no_header, "cache-control"}]).
+
+alias() ->
+ [{doc, "Test mod_alias"}].
+
+alias(Config) when is_list(Config) ->
+ ok = http_status("GET /pics/icon.sheet.gif ", Config,
+ [{statuscode, 200},
+ {header, "Content-Type","image/gif"},
+ {header, "Server"},
+ {header, "Date"}]),
+
+ ok = http_status("GET / ", Config,
+ [{statuscode, 200},
+ {header, "Content-Type","text/html"},
+ {header, "Server"},
+ {header, "Date"}]),
+
+ ok = http_status("GET /misc/ ", Config,
+ [{statuscode, 200},
+ {header, "Content-Type","text/html"},
+ {header, "Server"},
+ {header, "Date"}]),
+
+ %% Check redirection if trailing slash is missing.
+ ok = http_status("GET /misc ", Config,
+ [{statuscode, 301},
+ {header, "Location"},
+ {header, "Content-Type","text/html"}]).
+
+
+%% auth_api() ->
+%% [{doc, "Test mod_auth API"}].
+
+%% auth_api(Config) when is_list(Config) ->
+%% Version = ?config(http_version, Config),
+%% Host = ?config(host, Config),
+%% ok = http_status("GET / ", Config,
+%% [{statuscode, 200}]),
+%% ok = auth_status(auth_request("/", "one", "WrongPassword", Version, Host), Config,
+%% [{statuscode, 200}]),
+
+%% %% Make sure Authenticate header is received even the second time
+%% %% we try a incorrect password! Otherwise a browser client will hang!
+%% ok = auth_status(auth_request("/" ++ AuthStoreType ++ "open/",
+%% "dummy", "WrongPassword", Host), Config,
+%% [{statuscode, 401},
+%% {header, "WWW-Authenticate"}]),
+%% ok = auth_status(auth_request("/" ++ AuthStoreType ++ "open/", "dummy", "WrongPassword",
+%% Host), Config, [{statuscode, 401},
+%% {header, "WWW-Authenticate"}]),
+
+%% %% Change the password to DummyPassword then try to add a user
+%% %% Get an error and set it to NoPassword
+%% ok = update_password(Node, ServerRoot, Host, Port, AuthStoreType ++
+%% "open", "NoPassword", "DummyPassword"),
+%% {error,bad_password} =
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "one",
+%% "onePassword", []),
+%% ok = update_password(Node, ServerRoot, Host, Port, AuthStoreType ++"open",
+%% "DummyPassword", "NoPassword"),
+
+%% %% Test /*open, require user one Aladdin
+%% remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ "open"),
+
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+%% "one", "onePassword", [{statuscode, 401}]),
+
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+%% "two", "twoPassword", [{statuscode, 401}]),
+
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+%% "Aladdin", "onePassword", [{statuscode, 401}]),
+
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "one",
+%% "onePassword", []),
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "two",
+%% "twoPassword", []),
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "open", "Aladdin",
+%% "AladdinPassword", []),
+
+%% {ok, [_|_]} = list_users(Node, ServerRoot, Host, Port,
+%% AuthStoreType++"open"),
+%% auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/",
+%% "one", "WrongPassword", [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/",
+%% "one", "onePassword", [{statuscode, 200}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+%% "two", "twoPassword", [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "open/",
+%% "Aladdin", "WrongPassword", [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "open/",
+%% "Aladdin", "AladdinPassword", [{statuscode, 200}]),
+
+%% remove_users(Node, ServerRoot, Host, Port, AuthStoreType++"open"),
+%% {ok, []} = list_users(Node, ServerRoot, Host, Port,
+%% AuthStoreType++"open"),
+
+%% %% Phase 2
+%% remove_users(Node, ServerRoot, Host, Port, AuthStoreType++"secret"),
+%% {ok, []} = list_users(Node, ServerRoot, Host, Port, AuthStoreType ++
+%% "secret"),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+%% "one", "onePassword", [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+%% "two", "twoPassword", [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++ "secret/",
+%% "three", "threePassword", [{statuscode, 401}]),
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret", "one",
+%% "onePassword",
+%% []),
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret",
+%% "two", "twoPassword", []),
+%% add_user(Node, ServerRoot, Port, AuthStoreType++"secret", "Aladdin",
+%% "AladdinPassword",[]),
+%% add_group_member(Node, ServerRoot, Port, AuthStoreType ++ "secret",
+%% "one", "group1"),
+%% add_group_member(Node, ServerRoot, Port, AuthStoreType ++ "secret",
+%% "two", "group1"),
+%% add_group_member(Node, ServerRoot, Port, AuthStoreType ++
+%% "secret", "Aladdin", "group2"),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+%% "one", "onePassword", [{statuscode, 200}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+%% "two", "twoPassword", [{statuscode, 200}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+%% "Aladdin", "AladdinPassword", [{statuscode, 200}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++ "secret/",
+%% "three", "threePassword", [{statuscode, 401}]),
+%% remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++ "secret"),
+%% {ok, []} = list_users(Node, ServerRoot, Host, Port,
+%% AuthStoreType ++ "secret"),
+%% remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++ "secret"),
+%% Directory = filename:join([ServerRoot, "htdocs", AuthStoreType ++
+%% "secret"]),
+%% {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory),
+
+%% %% Phase 3
+%% remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++
+%% "secret/top_secret"),
+%% remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++
+%% "secret/top_secret"),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+%% "secret/top_secret/",
+%% "three", "threePassword", [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+%% "secret/top_secret/", "two", "twoPassword",
+%% [{statuscode, 401}]),
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++
+%% "secret/top_secret","three",
+%% "threePassword",[]),
+%% add_user(Node, ServerRoot, Port, AuthStoreType ++ "secret/top_secret",
+%% "two","twoPassword", []),
+%% add_group_member(Node, ServerRoot, Port, AuthStoreType ++
+%% "secret/top_secret",
+%% "three", "group3"),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+%% "secret/top_secret/", "three", "threePassword",
+%% [{statuscode, 200}]),
+%% auth_request(Type, Host, Port, Node,"/" ++ AuthStoreType ++
+%% "secret/top_secret/", "two", "twoPassword",
+%% [{statuscode, 401}]),
+%% add_group_member(Node, ServerRoot, Port, AuthStoreType ++
+%% "secret/top_secret",
+%% "two", "group3"),
+%% auth_request(Type,Host,Port,Node,"/" ++ AuthStoreType ++
+%% "secret/top_secret/",
+%% "two", "twoPassword", [{statuscode, 200}]),
+%% remove_users(Node, ServerRoot, Host, Port, AuthStoreType ++
+%% "secret/top_secret"),
+%% {ok, []} = list_users(Node, ServerRoot, Host, Port,
+%% AuthStoreType ++ "secret/top_secret"),
+%% remove_groups(Node, ServerRoot, Host, Port, AuthStoreType ++
+%% "secret/top_secret"),
+%% Directory2 = filename:join([ServerRoot, "htdocs",
+%% AuthStoreType ++ "secret/top_secret"]),
+%% {ok, []} = list_groups(Node, ServerRoot, Host, Port, Directory2),
+%% auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++
+%% "secret/top_secret/", "two", "twoPassword",
+%% [{statuscode, 401}]),
+%% auth_request(Type, Host, Port, Node, "/" ++ AuthStoreType ++
+%% "secret/top_secret/","three", "threePassword",
+%% [{statuscode, 401}]).
%%--------------------------------------------------------------------
-ticket_5775(doc) ->
- ["Tests that content-length is correct"];
-ticket_5775(suite) ->
- [];
-ticket_5775(Config) ->
- ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
- "GET /cgi-bin/erl/httpd_example:get_bin "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok.
-ticket_5865(doc) ->
- ["Tests that a header without last-modified is handled"];
-ticket_5865(suite) ->
- [];
-ticket_5865(Config) ->
- ?SKIP(as_of_r15_behaviour_of_calendar_has_changed),
- Host = ?config(host,Config),
- ServerRoot = ?config(server_root, Config),
- DocRoot = filename:join([ServerRoot, "htdocs"]),
- File = filename:join([DocRoot,"last_modified.html"]),
-
- Bad_mtime = case test_server:os_type() of
- {win32, _} ->
- {{1600,12,31},{23,59,59}};
- {unix, _} ->
- {{1969,12,31},{23,59,59}}
- end,
-
- {ok,FI}=file:read_file_info(File),
-
- case file:write_file_info(File,FI#file_info{mtime=Bad_mtime}) of
- ok ->
- ok = httpd_test_lib:verify_request(ip_comm, Host,
- ?IP_PORT, ?config(node, Config),
- "GET /last_modified.html"
- " HTTP/1.1\r\nHost:"
- ++Host++"\r\n\r\n",
+%% Internal functions -----------------------------------
+%%--------------------------------------------------------------------
+
+do_max_clients(Config) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ start_blocker(Config),
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request("GET /index.html ", Version, Host),
+ [{statuscode, 503},
+ {version, Version}]),
+ receive
+ after 2000 ->
+ ok = httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request("GET /index.html ", Version, Host),
[{statuscode, 200},
- {no_last_modified,
- "last-modified"}]),
- ok;
- {error, Reason} ->
- Fault =
- io_lib:format("Attempt to change the file info to set the"
- " preconditions of the test case failed ~p~n",
- [Reason]),
- {skip, Fault}
+ {version, Version}])
end.
-ticket_5913(doc) ->
- ["Tests that a header without last-modified is handled"];
-ticket_5913(suite) -> [];
-ticket_5913(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
- "GET /cgi-bin/erl/httpd_example:get_bin "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok.
+setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
+ CgiDir = filename:join(ServerRoot, "cgi-bin"),
+ AuthDir = filename:join(ServerRoot, "auth"),
+ PicsDir = filename:join(ServerRoot, "icons"),
-ticket_6003(doc) ->
- ["Tests that a URI with a bad hexadecimal code is handled"];
-ticket_6003(suite) -> [];
-ticket_6003(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
- "GET http://www.erlang.org/%skalle "
- "HTTP/1.0\r\n\r\n",
- [{statuscode, 400},
- {version, "HTTP/1.0"}]),
- ok.
+ ok = file:make_dir(ServerRoot),
+ ok = file:make_dir(DocRoot),
+ ok = file:make_dir(CgiDir),
+ ok = file:make_dir(AuthDir),
+ ok = file:make_dir(PicsDir),
+
+ DocSrc = filename:join(DataDir, "server_root/htdocs"),
+ AuthSrc = filename:join(DataDir, "server_root/auth"),
+ CgiSrc = filename:join(DataDir, "server_root/cgi-bin"),
+ PicsSrc = filename:join(DataDir, "server_root/icons"),
+
+ inets_test_lib:copy_dirs(DocSrc, DocRoot),
+ inets_test_lib:copy_dirs(AuthSrc, AuthDir),
+ inets_test_lib:copy_dirs(CgiSrc, CgiDir),
+ inets_test_lib:copy_dirs(PicsSrc, PicsDir),
+
+ Cgi = case test_server:os_type() of
+ {win32, _} ->
+ "cgi_echo.exe";
+ _ ->
+ "cgi_echo"
+ end,
-ticket_7304(doc) ->
- ["Tests missing CR in delimiter"];
-ticket_7304(suite) ->
- [];
-ticket_7304(Config) ->
- ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
- ?IP_PORT, ?config(node, Config),
- "GET / HTTP/1.0\r\n\n",
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok.
+ inets_test_lib:copy_file(Cgi, DataDir, CgiDir),
+ AbsCgi = filename:join([CgiDir, Cgi]),
+ {ok, FileInfo} = file:read_file_info(AbsCgi),
+ ok = file:write_file_info(AbsCgi, FileInfo#file_info{mode = 8#00755}),
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-dos_hostname(Type, Port, Host, Node, Max) ->
- H1 = {"", 200},
- H2 = {"dummy-host.ericsson.se", 200},
- TooLongHeader = lists:append(lists:duplicate(Max + 1, "a")),
- H3 = {TooLongHeader, 403},
- Hosts = [H1,H2,H3],
- dos_hostname_poll(Type, Host, Port, Node, Hosts).
+ EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]),
+ {ok, FileInfo1} = file:read_file_info(EnvCGI),
+ ok = file:write_file_info(EnvCGI,
+ FileInfo1#file_info{mode = 8#00755}).
-%% make_ipv6(T) when is_tuple(T) andalso (size(T) =:= 8) ->
-%% make_ipv6(tuple_to_list(T));
+start_apps(https) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(_) ->
+ ok.
-%% make_ipv6([_, _, _, _, _, _, _, _] = IPV6) ->
-%% lists:flatten(io_lib:format("~s:~s:~s:~s:~s:~s:~s:~s", IPV6)).
+server_start(_, HttpdConfig) ->
+ {ok, Pid} = inets:start(httpd, HttpdConfig),
+ Serv = inets:services_info(),
+ {value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
+ {Pid, proplists:get_value(port, Info)}.
-%%--------------------------------------------------------------------
-%% Other help functions
-create_config(Config, Access, FileName) ->
+server_config(http, Config) ->
ServerRoot = ?config(server_root, Config),
- TcTopDir = ?config(tc_top_dir, Config),
- Port = ?config(port, Config),
- Type = ?config(sock_type, Config),
- Host = ?config(host, Config),
- Mods = io_lib:format("~p", [httpd_mod]),
- Funcs = io_lib:format("~p", [ssl_password_cb]),
- MaxHdrSz = io_lib:format("~p", [256]),
- MaxHdrAct = io_lib:format("~p", [close]),
-
- io:format(user,
- "create_config -> "
- "~n ServerRoot: ~p"
- "~n TcTopDir: ~p"
- "~n Type: ~p"
- "~n Port: ~p"
- "~n Host: ~p"
- "~n", [ServerRoot, TcTopDir, Port, Type, Host]),
-
- SSL =
- if
- (Type =:= ssl) orelse
- (Type =:= essl) ->
- [cline(["SSLCertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCertificateKeyFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCACertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLPasswordCallbackModule ", Mods]),
- cline(["SSLPasswordCallbackFunction ", Funcs]),
- cline(["SSLVerifyClient 0"]),
- cline(["SSLVerifyDepth 1"])];
- true ->
- []
- end,
- ModOrder =
- case Access of
- mod_htaccess ->
- "Modules mod_alias mod_htaccess mod_auth "
- "mod_security "
- "mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_include mod_dir "
- "mod_range mod_get "
- "mod_head mod_log mod_disk_log";
- _ ->
- "Modules mod_alias mod_auth mod_security "
- "mod_responsecontrol mod_trace mod_esi "
- "mod_actions mod_cgi mod_include mod_dir "
- "mod_range mod_get "
- "mod_head mod_log mod_disk_log"
- end,
+ [{port, 0},
+ {server_name,"httpd_test"},
+ {server_root, ServerRoot},
+ {document_root, ?config(doc_root, Config)},
+ {bind_address, any},
+ {ipfamily, inet},
+ {max_header_size, 256},
+ {max_header_action, close},
+ {mime_types, [{"html","text/html"},{"htm","text/html"}, {"shtml","text/html"},
+ {"gif", "image/gif"}]},
+ {alias, {"/icons/", filename:join(ServerRoot,"icons") ++ "/"}},
+ {alias, {"/pics/", filename:join(ServerRoot,"icons") ++ "/"}},
+ {script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}},
+ {script_alias, {"/htbin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}},
+ {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}},
+ {eval_script_alias, {"/eval", [httpd_example, io]}}
+ ] ++ auth_conf(ServerRoot);
+
+server_config(http_limit, Config) ->
+ [{max_clients, 1}] ++ server_config(http, Config);
- %% The test suite currently does not handle an explicit BindAddress.
- %% They assume any has been used, that is Addr is always set to undefined!
-
- %% {ok, Hostname} = inet:gethostname(),
- %% {ok, Addr} = inet:getaddr(Hostname, inet6),
- %% AddrStr = make_ipv6(Addr),
- %% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])),
-
- BindAddress = "*|inet",
- %% BindAddress = "*",
-
- HttpConfig = [
- cline(["Port ", integer_to_list(Port)]),
- cline(["ServerName ", Host]),
- cline(["SocketType ", atom_to_list(Type)]),
- cline([ModOrder]),
- %% cline(["LogFormat ", "erlang"]),
- cline(["ServerAdmin [email protected]"]),
- cline(["BindAddress ", BindAddress]),
- cline(["ServerRoot ", ServerRoot]),
- cline(["ErrorLog ", TcTopDir,
- "/logs/error_log_", integer_to_list(Port)]),
- cline(["TransferLog ", TcTopDir,
- "/logs/access_log_", integer_to_list(Port)]),
- cline(["SecurityLog ", TcTopDir,
- "/logs/security_log_", integer_to_list(Port)]),
- cline(["ErrorDiskLog ", TcTopDir,
- "/logs/error_disk_log_", integer_to_list(Port)]),
- cline(["ErrorDiskLogSize ", "190000 ", "11"]),
- cline(["TransferDiskLog ", TcTopDir,
- "/logs/access_disk_log_", integer_to_list(Port)]),
- cline(["TransferDiskLogSize ", "200000 ", "10"]),
- cline(["SecurityDiskLog ", TcTopDir,
- "/logs/security_disk_log_", integer_to_list(Port)]),
- cline(["SecurityDiskLogSize ", "210000 ", "9"]),
- cline(["MaxClients 10"]),
- cline(["MaxHeaderSize ", MaxHdrSz]),
- cline(["MaxHeaderAction ", MaxHdrAct]),
- cline(["DocumentRoot ",
- filename:join(ServerRoot, "htdocs")]),
- cline(["DirectoryIndex ", "index.html ", "welcome.html"]),
- cline(["DefaultType ", "text/plain"]),
- SSL,
- mod_alias_config(ServerRoot),
-
- config_directory(filename:join([ServerRoot,"htdocs",
- "open"]),
- "Open Area",
- filename:join(ServerRoot, "auth/passwd"),
- filename:join(ServerRoot, "auth/group"),
- plain,
- "user one Aladdin",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "secret"]),
- "Secret Area",
- filename:join(ServerRoot, "auth/passwd"),
- filename:join(ServerRoot, "auth/group"),
- plain,
- "group group1 group2",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "secret",
- "top_secret"]),
- "Top Secret Area",
- filename:join(ServerRoot, "auth/passwd"),
- filename:join(ServerRoot, "auth/group"),
- plain,
- "group group3",
- filename:join(ServerRoot, "security_data")),
-
- config_directory(filename:join([ServerRoot,"htdocs",
- "dets_open"]),
- "Dets Open Area",
- filename:join(ServerRoot, "passwd"),
- filename:join(ServerRoot, "group"),
- dets,
- "user one Aladdin",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "dets_secret"]),
- "Dets Secret Area",
- filename:join(ServerRoot, "passwd"),
- filename:join(ServerRoot, "group"),
- dets,
- "group group1 group2",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "dets_secret",
- "top_secret"]),
- "Dets Top Secret Area",
- filename:join(ServerRoot, "passwd"),
- filename:join(ServerRoot, "group"),
- dets,
- "group group3",
- filename:join(ServerRoot, "security_data")),
-
- config_directory(filename:join([ServerRoot,"htdocs",
- "mnesia_open"]),
- "Mnesia Open Area",
- false,
- false,
- mnesia,
- "user one Aladdin",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join([ServerRoot,"htdocs",
- "mnesia_secret"]),
- "Mnesia Secret Area",
- false,
- false,
- mnesia,
- "group group1 group2",
- filename:join(ServerRoot, "security_data")),
- config_directory(filename:join(
- [ServerRoot, "htdocs", "mnesia_secret",
- "top_secret"]),
- "Mnesia Top Secret Area",
- false,
- false,
- mnesia,
- "group group3",
- filename:join(ServerRoot, "security_data"))
- ],
- ConfigFile = filename:join([TcTopDir, FileName]),
- {ok, Fd} = file:open(ConfigFile, [write]),
- ok = file:write(Fd, lists:flatten(HttpConfig)),
- ok = file:close(Fd).
-
-config_directory(Dir, AuthName, AuthUserFile, AuthGroupFile, AuthDBType,
- Require, SF) ->
- file:delete(SF),
- [
- cline(["<Directory ", Dir, ">"]),
- cline(["SecurityDataFile ", SF]),
- cline(["SecurityMaxRetries 3"]),
- cline(["SecurityFailExpireTime ", integer_to_list(?FAIL_EXPIRE_TIME)]),
- cline(["SecurityBlockTime 1"]),
- cline(["SecurityAuthTimeout ", integer_to_list(?AUTH_TIMEOUT)]),
- cline(["SecurityCallbackModule ", "httpd_mod"]),
- cline_if_set("AuthUserFile", AuthUserFile),
- cline_if_set("AuthGroupFile", AuthGroupFile),
- cline_if_set("AuthName", AuthName),
- cline_if_set("AuthDBType", AuthDBType),
- cline(["require ", Require]),
- cline(["</Directory>\r\n"])
+server_config(_, _) ->
+ [].
+
+http_request(Request, "HTTP/1.1" = Version, Host, {Headers, Body}) ->
+ Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n" ++ Headers ++ "\r\n" ++ Body;
+http_request(Request, Version, _, {Headers, Body}) ->
+ Request ++ Version ++ "\r\n" ++ Headers ++ "\r\n" ++ Body.
+
+http_request(Request, "HTTP/1.1" = Version, Host) ->
+ Request ++ Version ++ "\r\nhost:" ++ Host ++ "\r\n\r\n";
+http_request(Request, Version, _) ->
+ Request ++ Version ++ "\r\n\r\n".
+
+auth_request(Path, User, Passwd, "HTTP/1.1" = Version, Host) ->
+ "GET " ++ Path ++ " " ++ Version ++ "\r\nhost:" ++ Host ++
+ "\r\nAuthorization: Basic " ++
+ base64:encode_to_string(User++":"++Passwd) ++
+ "\r\n\r\n";
+auth_request(Path, User, Passwd, Version, _Host) ->
+ "GET " ++ Path ++ " " ++ Version ++
+ "\r\nAuthorization: Basic " ++
+ base64:encode_to_string(User++":"++Passwd) ++
+ "\r\n\r\n".
+
+head_status("HTTP/0.9") ->
+ 501; %% Not implemented in HTTP/0.9
+head_status(_) ->
+ 200.
+
+auth_conf(Root) ->
+ [{directory, {filename:join(Root, "htdocs/open"),
+ [{auth_type, plain},
+ {auth_name, "Open Area"},
+ {auth_user_file, filename:join(Root, "auth/passwd")},
+ {auth_group_file, filename:join(Root, "auth/group")},
+ {require_user, ["one", "Aladdin"]}]}},
+ {directory, {filename:join(Root, "htdocs/secret"),
+ [{auth_type, plain},
+ {auth_name, "Secret Area"},
+ {auth_user_file, filename:join(Root, "auth/passwd")},
+ {auth_group_file, filename:join(Root, "auth/group")},
+ {require_group, ["group1", "group2"]}]}},
+ {directory, {filename:join(Root, "htdocs/secret/top_secret"),
+ [{auth_type, plain},
+ {auth_name, "Top Secret Area"},
+ {auth_user_file, filename:join(Root, "auth/passwd")},
+ {auth_group_file, filename:join(Root, "auth/group")},
+ {require_group, ["group3"]}]}},
+ {directory, {filename:join(Root, "htdocs/open"),
+ [{auth_type, mnesia},
+ {auth_name, "Open Area"},
+ {auth_user_file, filename:join(Root, "auth/passwd")},
+ {auth_group_file, filename:join(Root, "auth/group")},
+ {require_user, ["one", "Aladdin"]}]}},
+ {directory, {filename:join(Root, "htdocs/secret"),
+ [{auth_type, mnesia},
+ {auth_name, "Secret Area"},
+ {auth_user_file, filename:join(Root, "auth/passwd")},
+ {auth_group_file, filename:join(Root, "auth/group")},
+ {require_group, ["group1", "group2"]}]}}
].
-mod_alias_config(Root) ->
- [
- cline(["Alias /icons/ ", filename:join(Root,"icons"), "/"]),
- cline(["Alias /pics/ ", filename:join(Root, "icons"), "/"]),
- cline(["ScriptAlias /cgi-bin/ ", filename:join(Root, "cgi-bin"), "/"]),
- cline(["ScriptAlias /htbin/ ", filename:join(Root, "cgi-bin"), "/"]),
- cline(["ErlScriptAlias /cgi-bin/erl httpd_example io"]),
- cline(["EvalScriptAlias /eval httpd_example io"])
- ].
-cline(List) ->
- lists:flatten([List, "\r\n"]).
+http_status(Request, Config, Expected) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request(Request, Version, Host),
+ Expected ++ [{version, Version}]).
-cline_if_set(_, false) ->
- [];
-cline_if_set(Name, Var) when is_list(Var) ->
- cline([Name, " ", Var]);
-cline_if_set(Name, Var) when is_atom(Var) ->
- cline([Name, " ", atom_to_list(Var)]).
+http_status(Request, HeadersAndBody, Config, Expected) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request(Request, Version, Host, HeadersAndBody),
+ Expected ++ [{version, Version}]).
-getaddr() ->
- {ok,HostName} = inet:gethostname(),
- {ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet),
- lists:flatten(io_lib:format("~p.~p.~p.~p",[A1,A2,A3,A4])).
+auth_status(AuthRequest, Config, Expected) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ AuthRequest,
+ Expected ++ [{version, Version}]).
+
+basic_auth_requiered(Config) ->
+ ok = http_status("GET /open/ ", Config, [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+ ok = http_status("GET /secret/ ", Config, [{statuscode, 401},
+ {header, "WWW-Authenticate"}]),
+ ok = http_status("GET /secret/top_secret/ ", Config, [{statuscode, 401},
+ {header, "WWW-Authenticate"}]).
start_mnesia(Node) ->
case rpc:call(Node, ?MODULE, cleanup_mnesia, []) of
ok ->
ok;
Other ->
- tsf({failed_to_cleanup_mnesia, Other})
+ ct:fail({failed_to_cleanup_mnesia, Other})
end,
case rpc:call(Node, ?MODULE, setup_mnesia, []) of
{atomic, ok} ->
ok;
Other2 ->
- tsf({failed_to_setup_mnesia, Other2})
+ ct:fail({failed_to_setup_mnesia, Other2})
end,
ok.
@@ -2568,13 +758,13 @@ setup_mnesia(Nodes) ->
ok = mnesia:create_schema(Nodes),
ok = mnesia:start(),
{atomic, ok} = mnesia:create_table(httpd_user,
- [{attributes,
- record_info(fields, httpd_user)},
+ [{attributes,
+ record_info(fields, httpd_user)},
{disc_copies,Nodes}, {type, set}]),
{atomic, ok} = mnesia:create_table(httpd_group,
- [{attributes,
+ [{attributes,
record_info(fields,
- httpd_group)},
+ httpd_group)},
{disc_copies,Nodes}, {type,bag}]).
cleanup_mnesia() ->
@@ -2585,199 +775,23 @@ cleanup_mnesia() ->
mnesia:delete_schema([node()]),
ok.
-create_htaccess_data(Path, IpAddress)->
- create_htaccess_dirs(Path),
-
- create_html_file(filename:join([Path,"ht/open/dummy.html"])),
- create_html_file(filename:join([Path,"ht/blocknet/dummy.html"])),
- create_html_file(filename:join([Path,"ht/secret/dummy.html"])),
- create_html_file(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
+start_blocker(Config) ->
+ spawn(httpd_SUITE, init_blocker, [self(), Config]),
+ receive
+ blocker_start ->
+ ok
+ end.
- create_htaccess_file(filename:join([Path,"ht/open/.htaccess"]),
- Path, "user one Aladdin"),
- create_htaccess_file(filename:join([Path,"ht/secret/.htaccess"]),
- Path, "group group1 group2"),
- create_htaccess_file(filename:join([Path,
- "ht/secret/top_secret/.htaccess"]),
- Path, "user four"),
- create_htaccess_file(filename:join([Path,"ht/blocknet/.htaccess"]),
- Path, nouser, IpAddress),
-
- create_user_group_file(filename:join([Path,"ht","users.file"]),
- "one:OnePassword\ntwo:TwoPassword\nthree:"
- "ThreePassword\nfour:FourPassword\nAladdin:"
- "AladdinPassword"),
- create_user_group_file(filename:join([Path,"ht","groups.file"]),
- "group1: two one\ngroup2: two three").
-
-create_html_file(PathAndFileName)->
- file:write_file(PathAndFileName,list_to_binary(
- "<html><head><title>test</title></head>
- <body>testar</body></html>")).
-
-create_htaccess_file(PathAndFileName, BaseDir, RequireData)->
- file:write_file(PathAndFileName,
- list_to_binary(
- "AuthUserFile "++ BaseDir ++
- "/ht/users.file\nAuthGroupFile "++ BaseDir
- ++ "/ht/groups.file\nAuthName Test\nAuthType"
- " Basic\n<Limit>\nrequire " ++ RequireData ++
- "\n</Limit>")).
-
-create_htaccess_file(PathAndFileName, BaseDir, nouser, IpAddress)->
- file:write_file(PathAndFileName,list_to_binary(
- "AuthUserFile "++ BaseDir ++
- "/ht/users.file\nAuthGroupFile " ++
- BaseDir ++ "/ht/groups.file\nAuthName"
- " Test\nAuthType"
- " Basic\n<Limit GET>\n\tallow from " ++
- format_ip(IpAddress,
- string:rchr(IpAddress,$.)) ++
- "\n</Limit>")).
-
-create_user_group_file(PathAndFileName, Data)->
- file:write_file(PathAndFileName, list_to_binary(Data)).
-
-create_htaccess_dirs(Path)->
- ok = file:make_dir(filename:join([Path,"ht"])),
- ok = file:make_dir(filename:join([Path,"ht/open"])),
- ok = file:make_dir(filename:join([Path,"ht/blocknet"])),
- ok = file:make_dir(filename:join([Path,"ht/secret"])),
- ok = file:make_dir(filename:join([Path,"ht/secret/top_secret"])).
-
-remove_htaccess_dirs(Path)->
- file:del_dir(filename:join([Path,"ht/secret/top_secret"])),
- file:del_dir(filename:join([Path,"ht/secret"])),
- file:del_dir(filename:join([Path,"ht/blocknet"])),
- file:del_dir(filename:join([Path,"ht/open"])),
- file:del_dir(filename:join([Path,"ht"])).
-
-format_ip(IpAddress,Pos)when Pos > 0->
- case lists:nth(Pos,IpAddress) of
- $.->
- case lists:nth(Pos-2,IpAddress) of
- $.->
- format_ip(IpAddress,Pos-3);
- _->
- lists:sublist(IpAddress,Pos-2) ++ "."
- end;
- _ ->
- format_ip(IpAddress,Pos-1)
- end;
-
-format_ip(IpAddress, _Pos)->
- "1" ++ IpAddress.
-
-remove_htaccess(Path)->
- file:delete(filename:join([Path,"ht/open/dummy.html"])),
- file:delete(filename:join([Path,"ht/secret/dummy.html"])),
- file:delete(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
- file:delete(filename:join([Path,"ht/blocknet/dummy.html"])),
- file:delete(filename:join([Path,"ht/blocknet/.htaccess"])),
- file:delete(filename:join([Path,"ht/open/.htaccess"])),
- file:delete(filename:join([Path,"ht/secret/.htaccess"])),
- file:delete(filename:join([Path,"ht/secret/top_secret/.htaccess"])),
- file:delete(filename:join([Path,"ht","users.file"])),
- file:delete(filename:join([Path,"ht","groups.file"])),
- remove_htaccess_dirs(Path).
-
-
-dos_hostname_poll(Type, Host, Port, Node, Hosts) ->
- [dos_hostname_poll1(Type, Host, Port, Node, Host1, Code)
- || {Host1,Code} <- Hosts].
-
-dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) ->
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
- dos_hostname_request(Host1),
- [{statuscode, Code},
- {version, "HTTP/1.0"}]).
-
-dos_hostname_request(Host) ->
- "GET / HTTP/1.0\r\n" ++ Host ++ "\r\n\r\n".
-
-get_nof_clients(Mode, Load) ->
- get_nof_clients(test_server:os_type(), Mode, Load).
-
-get_nof_clients(vxworks, _, light) -> 1;
-get_nof_clients(vxworks, ip_comm, medium) -> 3;
-get_nof_clients(vxworks, ssl, medium) -> 3;
-get_nof_clients(vxworks, ip_comm, heavy) -> 5;
-get_nof_clients(vxworks, ssl, heavy) -> 5;
-get_nof_clients(_, ip_comm, light) -> 5;
-get_nof_clients(_, ssl, light) -> 2;
-get_nof_clients(_, ip_comm, medium) -> 10;
-get_nof_clients(_, ssl, medium) -> 4;
-get_nof_clients(_, ip_comm, heavy) -> 20;
-get_nof_clients(_, ssl, heavy) -> 6.
-
-%% Make a file 100 bytes long containing 012...9*10
-create_range_data(Path) ->
- PathAndFileName=filename:join([Path,"range.txt"]),
- file:write_file(PathAndFileName,list_to_binary(["12345678901234567890",
- "12345678901234567890",
- "12345678901234567890",
- "12345678901234567890",
- "12345678901234567890"])).
-
-create_ipv6_config(Config, FileName, Ipv6Address) ->
- ServerRoot = ?config(server_root, Config),
- TcTopDir = ?config(tc_top_dir, Config),
- Port = ?config(port, Config),
- SockType = ?config(sock_type, Config),
- Mods = io_lib:format("~p", [httpd_mod]),
- Funcs = io_lib:format("~p", [ssl_password_cb]),
- Host = ?config(ipv6_host, Config),
-
- MaxHdrSz = io_lib:format("~p", [256]),
- MaxHdrAct = io_lib:format("~p", [close]),
-
- Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
- " mod_include mod_dir mod_get mod_head"
- " mod_log mod_disk_log mod_trace",
-
- SSL =
- if
- (SockType =:= ssl) orelse
- (SockType =:= essl) ->
- [cline(["SSLCertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCertificateKeyFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLCACertificateFile ",
- filename:join(ServerRoot, "ssl/ssl_server.pem")]),
- cline(["SSLPasswordCallbackModule ", Mods]),
- cline(["SSLPasswordCallbackFunction ", Funcs]),
- cline(["SSLVerifyClient 0"]),
- cline(["SSLVerifyDepth 1"])];
- true ->
- []
- end,
+init_blocker(From, Config) ->
+ From ! blocker_start,
+ block(Config).
- BindAddress = "[" ++ Ipv6Address ++"]|inet6",
-
- HttpConfig =
- [cline(["BindAddress ", BindAddress]),
- cline(["Port ", integer_to_list(Port)]),
- cline(["ServerName ", Host]),
- cline(["SocketType ", atom_to_list(SockType)]),
- cline([Mod_order]),
- cline(["ServerRoot ", ServerRoot]),
- cline(["DocumentRoot ", filename:join(ServerRoot, "htdocs")]),
- cline(["MaxHeaderSize ",MaxHdrSz]),
- cline(["MaxHeaderAction ",MaxHdrAct]),
- cline(["DirectoryIndex ", "index.html "]),
- cline(["DefaultType ", "text/plain"]),
- SSL],
- ConfigFile = filename:join([TcTopDir,FileName]),
- {ok, Fd} = file:open(ConfigFile, [write]),
- ok = file:write(Fd, lists:flatten(HttpConfig)),
- ok = file:close(Fd).
-
-
-tsp(F) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
-tsp(F, A) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
-
-tsf(Reason) ->
- inets_test_lib:tsf(Reason).
+block(Config) ->
+ Version = ?config(http_version, Config),
+ Host = ?config(host, Config),
+ httpd_test_lib:verify_request(?config(type, Config), Host,
+ ?config(port, Config), ?config(node, Config),
+ http_request("GET /eval?httpd_example:delay(1000) ",
+ Version, Host),
+ [{statuscode, 200},
+ {version, Version}]).
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip b/lib/inets/test/httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
deleted file mode 100644
index 8d1c8b69c3..0000000000
--- a/lib/inets/test/httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_client.pem b/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_client.pem
deleted file mode 100644
index 8221139eb4..0000000000
--- a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_client.pem
+++ /dev/null
@@ -1,22 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIBPAIBAAJBAL6Ym/bgUvhhnPkw08sggGg8Tnp759ThGMEjkmDzhuJ3w3PfnF65
-mgHcgunku4G6LxAQfEUougJWf9Phmjj3oRUCAwEAAQJBAKMjvVvzZxFzfAlP4flc
-OI0AEayFokp04dtvtzuFN09f+aBo2dP18xHmKLCZvxrBOaRAROoQYscALiIVpN07
-GAECIQDfi+sSfAFaDlT3vzpL3xE5UEH6IzY8jWpaZfM1QaToJQIhANpEF50H4wGO
-8Sbh7dUutNd+s+NYUjsMySW2DjLKMsoxAiEAzzb2ftrdsempD0F+O0gZwiPIFKLB
-Kp33YLYyHEKuJtUCIDGi+pvDh2R7VWw6RRQOIyI+tjolg83aAoSI+oGiahqBAiEA
-xzmNNajwoaokvWvlaz0na8rhxu45grOvDrflBT9XvSQ=
------END RSA PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIICDDCCAbYCAQAwDQYJKoZIhvcNAQEEBQAwgZAxCzAJBgNVBAYTAlNFMRIwEAYD
-VQQIEwlTdG9ja2hvbG0xDzANBgNVBAcTBkFsdnNqbzEMMAoGA1UEChMDRVRYMQ4w
-DAYDVQQLEwVETi9TUDEXMBUGA1UEAxMOSm9ha2ltIEdyZWJlbm8xJTAjBgkqhkiG
-9w0BCQEWFmpvY2tlQGVyaXguZXJpY3Nzb24uc2UwHhcNOTcwNzE1MTUzNDM2WhcN
-MDMwMjIyMTUzNDM2WjCBkDELMAkGA1UEBhMCU0UxEjAQBgNVBAgTCVN0b2NraG9s
-bTEPMA0GA1UEBxMGQWx2c2pvMQwwCgYDVQQKEwNFVFgxDjAMBgNVBAsTBUROL1NQ
-MRcwFQYDVQQDEw5Kb2FraW0gR3JlYmVubzElMCMGCSqGSIb3DQEJARYWam9ja2VA
-ZXJpeC5lcmljc3Nvbi5zZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC+mJv24FL4
-YZz5MNPLIIBoPE56e+fU4RjBI5Jg84bid8Nz35xeuZoB3ILp5LuBui8QEHxFKLoC
-Vn/T4Zo496EVAgMBAAEwDQYJKoZIhvcNAQEEBQADQQBYxQVfTydyZCE0UXvZd7Ei
-josNsAaWJk9fFIJaG9uyXCEfg2dVgoT2eBk3D9DI+7OB+78isM5CVlFbL7hilvP8
------END CERTIFICATE-----
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_server.pem b/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_server.pem
deleted file mode 100644
index fe739c15f7..0000000000
--- a/lib/inets/test/httpd_SUITE_data/server_root/ssl/ssl_server.pem
+++ /dev/null
@@ -1,22 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIBOwIBAAJBAL9Bozj3BIjL5Cy8b3rjMT2kPZRychX4wz9bHoIIiKnKo1xXHYjw
-g3N9zWM1f1ZzMADwVry1uAInA8q09+7hL20CAwEAAQJACwu2ao7RozjrV64WXimK
-6X131P/7GMvCMwGHNIlbozqoOqmZcYrbKaF61l+XuwA2QvTo3ywW1Ivxcyr6TeAr
-PQIhAOX+WXT6yiqqwjt08kjBCJyMgfZtdAO6pc/6pKjNWiZfAiEA1OH1iPW/OQe5
-tlQXpiRVdLyneNsPygPRJc4Bdwu3hbMCIQDbI5pA56QxOzqOREOGJsb5wrciAfAE
-jZbnr72sSN2YqQIgAWFpvzagw9Tp/mWzNY+cwkIK7/yzsIKv04fveH8p9IMCIQCr
-td4IiukeUwXmPSvYM4uCE/+J89wEL9qU8Mlc3gDLXA==
------END RSA PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIICDDCCAbYCAQAwDQYJKoZIhvcNAQEEBQAwgZAxCzAJBgNVBAYTAlNFMRIwEAYD
-VQQIEwlTdG9ja2hvbG0xDzANBgNVBAcTBkFsdnNqbzEMMAoGA1UEChMDRVRYMQ4w
-DAYDVQQLEwVETi9TUDEXMBUGA1UEAxMOSm9ha2ltIEdyZWJlbm8xJTAjBgkqhkiG
-9w0BCQEWFmpvY2tlQGVyaXguZXJpY3Nzb24uc2UwHhcNOTcwNzE1MTUzMzQxWhcN
-MDMwMjIyMTUzMzQxWjCBkDELMAkGA1UEBhMCU0UxEjAQBgNVBAgTCVN0b2NraG9s
-bTEPMA0GA1UEBxMGQWx2c2pvMQwwCgYDVQQKEwNFVFgxDjAMBgNVBAsTBUROL1NQ
-MRcwFQYDVQQDEw5Kb2FraW0gR3JlYmVubzElMCMGCSqGSIb3DQEJARYWam9ja2VA
-ZXJpeC5lcmljc3Nvbi5zZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC/QaM49wSI
-y+QsvG964zE9pD2UcnIV+MM/Wx6CCIipyqNcVx2I8INzfc1jNX9WczAA8Fa8tbgC
-JwPKtPfu4S9tAgMBAAEwDQYJKoZIhvcNAQEEBQADQQAmXDY1CyJjzvQZX442kkHG
-ic9QFY1UuVfzokzNMwlHYl1Qx9zaodx0cJCrcH5GF9O9LJbhhV77LzoxT1Q5wZp5
------END CERTIFICATE-----
diff --git a/lib/inets/test/httpd_all.erl b/lib/inets/test/httpd_all.erl
new file mode 100644
index 0000000000..7ce1129bf5
--- /dev/null
+++ b/lib/inets/test/httpd_all.erl
@@ -0,0 +1,239 @@
+alias(Version, Type, Port, Host, Node) ->
+ Opts = [],
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
+ "GET /pics/icon.sheet.gif "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type","image/gif"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
+ "GET / " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type","text/html"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
+ "GET /misc/ " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type","text/html"},
+ {header, "Server"},
+ {header, "Date"},
+ {version, Version}]),
+
+ %% Check redirection if trailing slash is missing.
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
+ "GET /misc "++ Version ++ "\r\n\r\n",
+ [{statuscode, 301},
+ {header, "Location"},
+ {header, "Content-Type","text/html"},
+ {version, Version}]).
+
+
+head(Version, Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "HEAD /index.html " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {version, Version}]).
+
+
+get(Version, Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /index.html " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /fsize.shtml " ++ Version ++ "\r\nHost:"
+ ++ Host ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /secret/dummy.html "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 401},
+ {header, "WWW-Authenticate"},
+ {version, Version}]).
+
+esi(Version, Type, Port, Host, Node) ->
+ %% Check "ErlScriptAlias" and "EvalScriptAlias" directives
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /eval?httpd_example:print(\"Hi!\") "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /eval?not_allowed:print(\"Hi!\") "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 403},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /eval?httpd_example:undef(\"Hi!\") "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 500},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 400},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:get "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:"
+ "get?input=4711"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:"
+ "post " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/not_allowed:post "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 403},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:undef "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 404},
+ {version, Version}]),
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example/yahoo "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 302},
+ {version, Version}]),
+ %% Check "ErlScriptNoCache" directive (default: false)
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:get "
+ ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {no_header, "cache-control"},
+ {version, "HTTP/1.0"}]).
+
+cgi(Version, Type, Port, Host, Node) ->
+ {Script, Script2, Script3} =
+ case test_server:os_type() of
+ {win32, _} ->
+ {"printenv.bat", "printenv.sh", "cgi_echo.exe"};
+ _ ->
+ {"printenv.sh", "printenv.bat", "cgi_echo"}
+ end,
+
+ %% The length (> 100) is intentional
+ ok = httpd_test_lib:
+ verify_request(Type, Host, Port, Node,
+ "POST /cgi-bin/" ++ Script3 ++
+ Version ++ " \r\n"
+ "Content-Length:100 \r\n\r\n "
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ " \r\n\r\n",
+ [{statuscode, 200},
+ {version, Version},
+ {header, "content-type", "text/plain"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/"++ Script ++
+ " " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/not_there " ++
+ Version ++ "\r\n\r\n",
+ [{statuscode, 404},{statuscode, 500},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/"++ Script ++
+ "?Nisse:kkk?sss/lll " ++ Version ++ "\r\n\r\n",
+ [{statuscode, 200},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /cgi-bin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /htbin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /htbin/not_there "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},{statuscode, 500},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /htbin/"++ Script ++
+ "?Nisse:kkk?sss/lll HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /htbin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /htbin/"++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ %% Execute an existing, but bad CGI script..
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /htbin/"++ Script2 ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},
+ {version, "HTTP/1.0"}]),
+
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "POST /cgi-bin/"++ Script2 ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 404},
+ {version, "HTTP/1.0"}]),
+
+ %% Check "ScriptNoCache" directive (default: false)
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/" ++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {no_header, "cache-control"},
+ {version, "HTTP/1.0"}]).
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index 523cf9d38c..f75655db1d 100644
--- a/lib/inets/test/httpd_basic_SUITE.erl
+++ b/lib/inets/test/httpd_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,6 +19,7 @@
%%
-module(httpd_basic_SUITE).
+-include_lib("kernel/include/file.hrl").
-include_lib("common_test/include/ct.hrl").
-include("inets_test_lib.hrl").
@@ -33,9 +34,13 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[
uri_too_long_414,
- header_too_long_413,
+ header_too_long_413,
+ erl_script_nocache_opt,
+ script_nocache,
escaped_url_in_error_body,
- slowdose
+ script_timeout,
+ slowdose,
+ keep_alive_timeout
].
groups() ->
@@ -60,8 +65,10 @@ end_per_group(_GroupName, Config) ->
init_per_suite(Config) ->
tsp("init_per_suite -> entry with"
"~n Config: ~p", [Config]),
- ok = inets:start(),
+ inets_test_lib:stop_apps([inets]),
+ inets_test_lib:start_apps([inets]),
PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
Dummy =
"<HTML>
@@ -74,6 +81,21 @@ DUMMY
</HTML>",
DummyFile = filename:join([PrivDir,"dummy.html"]),
+ CgiDir = filename:join(PrivDir, "cgi-bin"),
+ ok = file:make_dir(CgiDir),
+ {CgiPrintEnv, CgiSleep} = case test_server:os_type() of
+ {win32, _} ->
+ {"printenv.bat", "cgi_sleep.exe"};
+ _ ->
+ {"printenv.sh", "cgi_sleep"}
+ end,
+ lists:foreach(
+ fun(Cgi) ->
+ inets_test_lib:copy_file(Cgi, DataDir, CgiDir),
+ AbsCgi = filename:join([CgiDir, Cgi]),
+ {ok, FileInfo} = file:read_file_info(AbsCgi),
+ ok = file:write_file_info(AbsCgi, FileInfo#file_info{mode = 8#00755})
+ end, [CgiPrintEnv, CgiSleep]),
{ok, Fd} = file:open(DummyFile, [write]),
ok = file:write(Fd, Dummy),
ok = file:close(Fd),
@@ -84,7 +106,8 @@ DUMMY
{document_root, PrivDir},
{bind_address, "localhost"}],
- [{httpd_conf, HttpdConf} | Config].
+ [{httpd_conf, HttpdConf}, {cgi_dir, CgiDir},
+ {cgi_printenv, CgiPrintEnv}, {cgi_sleep, CgiSleep} | Config].
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
@@ -178,6 +201,74 @@ header_too_long_413(Config) when is_list(Config) ->
{version, "HTTP/1.1"}]),
inets:stop(httpd, Pid).
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
+erl_script_nocache_opt(doc) ->
+ ["Test that too long headers's get 413 HTTP code"];
+erl_script_nocache_opt(suite) ->
+ [];
+erl_script_nocache_opt(Config) when is_list(Config) ->
+ HttpdConf = ?config(httpd_conf, Config),
+ {ok, Pid} = inets:start(httpd, [{port, 0}, {erl_script_nocache, true} | HttpdConf]),
+ Info = httpd:info(Pid),
+ Port = proplists:get_value(port, Info),
+ _Address = proplists:get_value(bind_address, Info),
+ URL1 = ?URL_START ++ integer_to_list(Port),
+ case httpc:request(get, {URL1 ++ "/dummy.html", []},
+ [{url_encode, false},
+ {version, "HTTP/1.0"}],
+ [{full_result, false}]) of
+ {ok, {200, _}} ->
+ ok
+ end,
+ inets:stop(httpd, Pid).
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
+script_nocache(doc) ->
+ ["Test nocache option for mod_cgi and mod_esi"];
+script_nocache(suite) ->
+ [];
+script_nocache(Config) when is_list(Config) ->
+ Normal = {no_header, "cache-control"},
+ NoCache = {header, "cache-control", "no-cache"},
+ verify_script_nocache(Config, false, false, Normal, Normal),
+ verify_script_nocache(Config, true, false, NoCache, Normal),
+ verify_script_nocache(Config, false, true, Normal, NoCache),
+ verify_script_nocache(Config, true, true, NoCache, NoCache),
+ ok.
+
+verify_script_nocache(Config, CgiNoCache, EsiNoCache, CgiOption, EsiOption) ->
+ HttpdConf = ?config(httpd_conf, Config),
+ CgiScript = ?config(cgi_printenv, Config),
+ CgiDir = ?config(cgi_dir, Config),
+ {ok, Pid} = inets:start(httpd, [{port, 0},
+ {script_alias,
+ {"/cgi-bin/", CgiDir ++ "/"}},
+ {script_nocache, CgiNoCache},
+ {erl_script_alias,
+ {"/cgi-bin/erl", [httpd_example,io]}},
+ {erl_script_nocache, EsiNoCache}
+ | HttpdConf]),
+ Info = httpd:info(Pid),
+ Port = proplists:get_value(port, Info),
+ Address = proplists:get_value(bind_address, Info),
+ ok = httpd_test_lib:verify_request(ip_comm, Address, Port, node(),
+ "GET /cgi-bin/" ++ CgiScript ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ CgiOption,
+ {version, "HTTP/1.0"}]),
+ ok = httpd_test_lib:verify_request(ip_comm, Address, Port, node(),
+ "GET /cgi-bin/erl/httpd_example:get "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ EsiOption,
+ {version, "HTTP/1.0"}]),
+ inets:stop(httpd, Pid).
+
%%-------------------------------------------------------------------------
%%-------------------------------------------------------------------------
@@ -279,6 +370,63 @@ escaped_url_in_error_body(Config) when is_list(Config) ->
inets:stop(httpd, Pid),
tsp("escaped_url_in_error_body -> done"),
ok.
+
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
+keep_alive_timeout(doc) ->
+ ["Test the keep_alive_timeout option"];
+keep_alive_timeout(suite) ->
+ [];
+keep_alive_timeout(Config) when is_list(Config) ->
+ HttpdConf = ?config(httpd_conf, Config),
+ {ok, Pid} = inets:start(httpd, [{port, 0}, {keep_alive, true}, {keep_alive_timeout, 2} | HttpdConf]),
+ Info = httpd:info(Pid),
+ Port = proplists:get_value(port, Info),
+ _Address = proplists:get_value(bind_address, Info),
+ {ok, S} = gen_tcp:connect("localhost", Port, []),
+ receive
+ after 3000 ->
+ {error, closed} = gen_tcp:send(S, "hey")
+ end,
+ inets:stop(httpd, Pid).
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
+script_timeout(doc) ->
+ ["Test the httpd script_timeout option"];
+script_timeout(suite) ->
+ [];
+script_timeout(Config) when is_list(Config) ->
+ verify_script_timeout(Config, 20, 200),
+ verify_script_timeout(Config, 5, 403),
+ ok.
+
+verify_script_timeout(Config, ScriptTimeout, StatusCode) ->
+ HttpdConf = ?config(httpd_conf, Config),
+ CgiScript = ?config(cgi_sleep, Config),
+ CgiDir = ?config(cgi_dir, Config),
+ {ok, Pid} = inets:start(httpd, [{port, 0},
+ {script_alias,
+ {"/cgi-bin/", CgiDir ++ "/"}},
+ {script_timeout, ScriptTimeout}
+ | HttpdConf]),
+ Info = httpd:info(Pid),
+ Port = proplists:get_value(port, Info),
+ Address = proplists:get_value(bind_address, Info),
+ ok = httpd_test_lib:verify_request(ip_comm, Address, Port, node(),
+ "GET /cgi-bin/" ++ CgiScript ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, StatusCode},
+ {version, "HTTP/1.0"}]),
+ inets:stop(httpd, Pid).
+
+
+%%-------------------------------------------------------------------------
+%%-------------------------------------------------------------------------
+
slowdose(doc) ->
["Testing minimum bytes per second option"];
slowdose(Config) when is_list(Config) ->
diff --git a/lib/inets/test/httpd_basic_SUITE_data/Makefile.src b/lib/inets/test/httpd_basic_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..9da2ed583f
--- /dev/null
+++ b/lib/inets/test/httpd_basic_SUITE_data/Makefile.src
@@ -0,0 +1,14 @@
+CC = @CC@
+LD = @LD@
+CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
+CROSSLDFLAGS = @CROSSLDFLAGS@
+
+PROGS = cgi_sleep@exe@
+
+all: $(PROGS)
+
+cgi_sleep@exe@: cgi_sleep@obj@
+ $(LD) $(CROSSLDFLAGS) -o cgi_sleep cgi_sleep@obj@ @LIBS@
+
+cgi_sleep@obj@: cgi_sleep.c
+ $(CC) -c -o cgi_sleep@obj@ $(CFLAGS) cgi_sleep.c
diff --git a/lib/inets/test/httpd_basic_SUITE_data/cgi_sleep.c b/lib/inets/test/httpd_basic_SUITE_data/cgi_sleep.c
new file mode 100644
index 0000000000..126bb23987
--- /dev/null
+++ b/lib/inets/test/httpd_basic_SUITE_data/cgi_sleep.c
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __WIN32__
+#include <windows.h>
+#include <fcntl.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+int main(void)
+{
+ unsigned int seconds = 10;
+
+#ifdef __WIN32__
+ Sleep(seconds * 1000);
+ _setmode(_fileno(stdout), _O_BINARY);
+#else
+ sleep(seconds);
+#endif
+
+ printf("Content-type: text/plain\r\n\r\n");
+ printf("Slept for %u seconds.\r\n", seconds);
+ exit(EXIT_SUCCESS);
+}
diff --git a/lib/inets/test/httpd_basic_SUITE_data/printenv.bat b/lib/inets/test/httpd_basic_SUITE_data/printenv.bat
new file mode 120000
index 0000000000..1bc8e52059
--- /dev/null
+++ b/lib/inets/test/httpd_basic_SUITE_data/printenv.bat
@@ -0,0 +1 @@
+../httpd_SUITE_data/server_root/cgi-bin/printenv.bat \ No newline at end of file
diff --git a/lib/inets/test/httpd_basic_SUITE_data/printenv.sh b/lib/inets/test/httpd_basic_SUITE_data/printenv.sh
new file mode 120000
index 0000000000..0136a3fa23
--- /dev/null
+++ b/lib/inets/test/httpd_basic_SUITE_data/printenv.sh
@@ -0,0 +1 @@
+../httpd_SUITE_data/server_root/cgi-bin/printenv.sh \ No newline at end of file
diff --git a/lib/inets/test/httpd_block.erl b/lib/inets/test/httpd_block.erl
index ac1bf43ff5..5c2cb3c51c 100644
--- a/lib/inets/test/httpd_block.erl
+++ b/lib/inets/test/httpd_block.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,8 +19,7 @@
%%
-module(httpd_block).
--include("test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
%% General testcases bodies called from httpd_SUITE
-export([block_disturbing_idle/4, block_non_disturbing_idle/4,
@@ -88,7 +87,7 @@ block_503(Type, Port, Host, Node) ->
block_disturbing_active(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Pid = long_poll(Type, Host, Port, Node, 200, 60000),
- test_server:sleep(15000),
+ ct:sleep(15000),
block_server(Node, Host, Port),
await_suite_failed_process_exit(Pid, "poller", 60000,
connection_closed),
@@ -100,7 +99,7 @@ block_disturbing_active(Type, Port, Host, Node) ->
block_non_disturbing_active(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- test_server:sleep(15000),
+ ct:sleep(15000),
ok = block_nd_server(Node, Host, Port),
await_normal_process_exit(Poller, "poller", 60000),
blocked = get_admin_state(Node, Host, Port),
@@ -111,7 +110,7 @@ block_non_disturbing_active(Type, Port, Host, Node) ->
block_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- test_server:sleep(15000),
+ ct:sleep(15000),
Blocker = blocker(Node, Host, Port, 50000),
await_normal_process_exit(Blocker, "blocker", 50000),
await_normal_process_exit(Poller, "poller", 30000),
@@ -123,7 +122,7 @@ block_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
block_disturbing_active_timeout_released(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Poller = long_poll(Type, Host, Port, Node, 200, 40000),
- test_server:sleep(5000),
+ ct:sleep(5000),
Blocker = blocker(Node, Host, Port, 10000),
await_normal_process_exit(Blocker, "blocker", 15000),
await_suite_failed_process_exit(Poller, "poller", 40000,
@@ -146,7 +145,7 @@ block_non_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
block_non_disturbing_active_timeout_released(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Poller = long_poll(Type, Host, Port, Node, 200, 45000),
- test_server:sleep(5000),
+ ct:sleep(5000),
Blocker = blocker_nd(Node, Host, Port ,10000, {error,timeout}),
await_normal_process_exit(Blocker, "blocker", 15000),
await_normal_process_exit(Poller, "poller", 50000),
@@ -157,9 +156,9 @@ block_non_disturbing_active_timeout_released(Type, Port, Host, Node) ->
disturbing_blocker_dies(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- test_server:sleep(5000),
+ ct:sleep(5000),
Blocker = blocker(Node, Host, Port, 10000),
- test_server:sleep(5000),
+ ct:sleep(5000),
exit(Blocker,simulate_blocker_crash),
await_normal_process_exit(Poller, "poller", 60000),
unblocked = get_admin_state(Node, Host, Port),
@@ -170,9 +169,9 @@ disturbing_blocker_dies(Type, Port, Host, Node) ->
non_disturbing_blocker_dies(Type, Port, Host, Node) ->
process_flag(trap_exit, true),
Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- test_server:sleep(5000),
+ ct:sleep(5000),
Blocker = blocker_nd(Node, Host, Port, 10000, ok),
- test_server:sleep(5000),
+ ct:sleep(5000),
exit(Blocker, simulate_blocker_crash),
await_normal_process_exit(Poller, "poller", 60000),
unblocked = get_admin_state(Node, Host, Port),
@@ -297,9 +296,12 @@ httpd_restart(Addr, Port) ->
make_name(Addr, Port) ->
httpd_util:make_name("httpd", Addr, Port).
-get_admin_state(Node, _Host, Port) ->
- Addr = undefined,
- rpc:call(Node, httpd, get_admin_state, [Addr, Port]).
+get_admin_state(_, _Host, Port) ->
+ Name = make_name(undefined, Port),
+ {status, _, _, StatusInfo} = sys:get_status(whereis(Name)),
+ [_, _,_, _, Prop] = StatusInfo,
+ State = state(Prop),
+ element(6, State).
validate_admin_state(Node, Host, Port, Expect) ->
io:format("try validating server admin state: ~p~n", [Expect]),
@@ -323,15 +325,15 @@ await_normal_process_exit(Pid, Name, Timeout) ->
io_lib:format("expected normal exit, "
"unexpected exit of ~s process: ~p",
[Name, Reason])),
- test_server:fail(Err)
+ ct:fail(Err)
after Timeout ->
- test_server:fail("timeout while waiting for " ++ Name)
+ ct:fail("timeout while waiting for " ++ Name)
end.
await_suite_failed_process_exit(Pid, Name, Timeout, Why) ->
receive
- {'EXIT', Pid, {suite_failed, Why}} ->
+ {'EXIT', Pid, {test_failed, Why}} ->
ok;
{'EXIT', Pid, Reason} ->
Err =
@@ -339,9 +341,9 @@ await_suite_failed_process_exit(Pid, Name, Timeout, Why) ->
io_lib:format("expected connection_closed, "
"unexpected exit of ~s process: ~p",
[Name, Reason])),
- test_server:fail(Err)
+ ct:fail(Err)
after Timeout ->
- test_server:fail("timeout while waiting for " ++ Name)
+ ct:fail("timeout while waiting for " ++ Name)
end.
long_poll(Type, Host, Port, Node, StatusCode, Timeout) ->
@@ -359,10 +361,13 @@ do_long_poll(Type, Host, Port, Node, StatusCode, Timeout) ->
ok ->
exit(normal);
Reason ->
- test_server:fail(Reason)
+ exit({test_failed, Reason})
end.
-
-
-
+state([{data,[{"State", State}]} | _]) ->
+ State;
+state([{data,[{"StateData", State}]} | _]) ->
+ State;
+state([_ | Rest]) ->
+ state(Rest).
diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl
index 387263ce58..558958424a 100644
--- a/lib/inets/test/httpd_mod.erl
+++ b/lib/inets/test/httpd_mod.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -40,7 +40,6 @@
%%-------------------------------------------------------------------------
alias(Type, Port, Host, Node) ->
%% This is very crude, but...
- tsp("alias -> Has IPv6 support: ~p", [inets_test_lib:has_ipv6_support()]),
Opts = [],
ok = httpd_test_lib:verify_request(Type, Host, Port, Opts, Node,
"GET /pics/icon.sheet.gif "
@@ -85,16 +84,7 @@ actions(Type, Port, Host, Node) ->
%%-------------------------------------------------------------------------
security(ServerRoot, Type, Port, Host, Node) ->
- tsp("security -> "
- "entry with"
- "~n ServerRoot: ~p"
- "~n Type: ~p"
- "~n Port: ~p"
- "~n Host: ~p"
- "~n Node: ~p", [ServerRoot, Type, Port, Host, Node]),
- tsp("security -> "
- "register - receive security events"),
global:register_name(mod_security_test, self()), % Receive events
tsp("security -> "
@@ -333,12 +323,6 @@ security(ServerRoot, Type, Port, Host, Node) ->
%%-------------------------------------------------------------------------
auth(Type, Port, Host, Node) ->
- tsp("auth -> "
- "entry with"
- "~n Type: ~p"
- "~n Port: ~p"
- "~n Host: ~p"
- "~n Node: ~p", [Type, Port, Host, Node]),
%% Authentication required!
ok = httpd_test_lib:verify_request(Type,Host,Port,Node,
@@ -750,11 +734,6 @@ htaccess(Type, Port, Host, Node) ->
{header, "WWW-Authenticate"}]).
%%--------------------------------------------------------------------
cgi(Type, Port, Host, Node) ->
-%% tsp("cgi -> entry with"
-%% "~n Type: ~p"
-%% "~n Port: ~p"
-%% "~n Host: ~p"
-%% "~n Node: ~p", []),
{Script, Script2, Script3} =
case test_server:os_type() of
{win32, _} ->
@@ -863,6 +842,14 @@ cgi(Type, Port, Host, Node) ->
{version, "HTTP/1.0"}]),
%% tsp("cgi -> done"),
+
+ %% Check "ScriptNoCache" directive (default: false)
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/" ++ Script ++
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {no_header, "cache-control"},
+ {version, "HTTP/1.0"}]),
ok.
@@ -920,6 +907,13 @@ esi(Type, Port, Host, Node) ->
" HTTP/1.0\r\n\r\n",
[{statuscode, 302},
{version, "HTTP/1.0"}]),
+ %% Check "ErlScriptNoCache" directive (default: false)
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example:get"
+ " HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {no_header, "cache-control"},
+ {version, "HTTP/1.0"}]),
ok.
diff --git a/lib/inets/test/httpd_mod_SUITE.erl b/lib/inets/test/httpd_mod_SUITE.erl
new file mode 100644
index 0000000000..07e2c2418a
--- /dev/null
+++ b/lib/inets/test/httpd_mod_SUITE.erl
@@ -0,0 +1,76 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013-2014. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%
+%% ct:run("../inets_test", httpd_mod_SUITE).
+-module(httpd_mod_SUITE).
+
+-include_lib("kernel/include/file.hrl").
+-include_lib("common_test/include/ct.hrl").
+-include("inets_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ {group, http},
+ {group, https}
+ ].
+
+groups() ->
+ [
+ {http, [], all_version_groups()},
+ {https, [], all_version_groups()}
+ {http_1_1, [], []},
+ {http_1_0, [], []},
+ {http_0_9, [], []},
+ {mod_alias, [], []},
+ {mod_actions, [], []},
+ {mod_security, [], []},
+ {mod_auth, [], []},
+ {mod_htaccess, [], []},
+ {mod_cgi, [], []},
+ {mod_esi, [], []},
+ {mod_head, [], []},
+ {configure, [], []}
+ ].
+
+all_version_groups ()->
+ [
+ {group, mod_alias},
+ {group, mod_actions},
+ {group, mod_security},
+ {group, mod_auth},
+ {group, mod_htaccess},
+ {group, mod_cgi},
+ {group, mod_esi},
+ {group, mod_head}
+ ].
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 4b33350cf2..970b0cd475 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -91,7 +91,7 @@ verify_request(SocketType, Host, Port, Node, RequestStr, Options, TimeOut)
when (is_integer(TimeOut) orelse (TimeOut =:= infinity)) ->
verify_request(SocketType, Host, Port, [], Node, RequestStr, Options, TimeOut).
-verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, TimeOut) ->
+verify_request(SocketType, Host, Port, TranspOpts0, Node, RequestStr, Options, TimeOut) ->
tsp("verify_request -> entry with"
"~n SocketType: ~p"
"~n Host: ~p"
@@ -100,7 +100,17 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
"~n Node: ~p"
"~n Options: ~p"
"~n TimeOut: ~p",
- [SocketType, Host, Port, TranspOpts, Node, Options, TimeOut]),
+ [SocketType, Host, Port, TranspOpts0, Node, Options, TimeOut]),
+
+ %% For now, until we modernize the httpd tests
+ TranspOpts =
+ case lists:member(inet6, TranspOpts0) of
+ true ->
+ TranspOpts0;
+ false ->
+ [inet | TranspOpts0]
+ end,
+
try inets_test_lib:connect_bin(SocketType, Host, Port, TranspOpts) of
{ok, Socket} ->
tsp("verify_request -> connected - now send message"),
@@ -177,12 +187,12 @@ request(#state{mfa = {Module, Function, Args},
{tcp_closed, Socket} ->
io:format("~p ~w[~w]request -> received (tcp) closed"
"~n", [self(), ?MODULE, ?LINE]),
- test_server:fail(connection_closed);
+ exit({test_failed, connection_closed});
{tcp_error, Socket, Reason} ->
io:format("~p ~w[~w]request -> received (tcp) error"
"~n Reason: ~p"
"~n", [self(), ?MODULE, ?LINE, Reason]),
- test_server:fail({tcp_error, Reason});
+ ct:fail({tcp_error, Reason});
{ssl, Socket, Data} ->
print(ssl, Data, State),
case Module:Function([Data | Args]) of
@@ -197,13 +207,13 @@ request(#state{mfa = {Module, Function, Args},
print(ssl, "closed", State),
State#state{body = hd(Args)};
{ssl_closed, Socket} ->
- test_server:fail(connection_closed);
+ exit({test_failed, connection_closed});
{ssl_error, Socket, Reason} ->
- test_server:fail({ssl_error, Reason})
+ ct:fail({ssl_error, Reason})
after TimeOut ->
io:format("~p ~w[~w]request -> timeout"
"~n", [self(), ?MODULE, ?LINE]),
- test_server:fail(connection_timed_out)
+ ct:fail(connection_timed_out)
end.
handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
@@ -267,7 +277,7 @@ handle_http_body(Body, State = #state{headers = Headers,
request(State#state{mfa = MFA}, 5000)
end;
false ->
- test_server:fail(body_too_big)
+ ct:fail(body_too_big)
end
end.
@@ -293,8 +303,7 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _},
list_to_integer(Headers#http_response_h.'content-length'),
Body).
-
-%%--------------------------------------------------------------------
+%--------------------------------------------------------------------
%% Internal functions
%%------------------------------------------------------------------
check_version(Version, Options) ->
@@ -352,7 +361,7 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) ->
tsf({wrong_header_field_value, LowerHeaderField, Header})
end,
do_validate(Header, Rest, N, P);
-do_validate(Header,[{no_last_modified, HeaderField}|Rest],N,P) ->
+do_validate(Header,[{no_header, HeaderField}|Rest],N,P) ->
case lists:keysearch(HeaderField,1,Header) of
{value,_} ->
tsf({wrong_header_field_value, HeaderField, Header});
@@ -396,7 +405,7 @@ check_body(_, _, _, _,_) ->
ok.
print(Proto, Data, #state{print = true}) ->
- test_server:format("Received ~p: ~p~n", [Proto, Data]);
+ ct:pal("Received ~p: ~p~n", [Proto, Data]);
print(_, _, #state{print = false}) ->
ok.
diff --git a/lib/inets/test/inets_SUITE.erl b/lib/inets/test/inets_SUITE.erl
index 6fa0f44d77..069c68fa1e 100644
--- a/lib/inets/test/inets_SUITE.erl
+++ b/lib/inets/test/inets_SUITE.erl
@@ -363,8 +363,6 @@ start_ftpc(suite) ->
[];
start_ftpc(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- inets:disable_trace(),
- inets:enable_trace(max, io, ftpc),
ok = inets:start(),
try
begin
@@ -393,16 +391,13 @@ start_ftpc(Config) when is_list(Config) ->
tsf(stand_alone_not_shutdown)
end,
ok = inets:stop(),
- inets:disable_trace(),
ok;
_ ->
- inets:disable_trace(),
{skip, "Unable to reach selected FTP server " ++ FtpdHost}
end
end
catch
throw:{error, not_found} ->
- inets:disable_trace(),
{skip, "No available FTP servers"}
end.
@@ -462,8 +457,6 @@ httpd_reload(Config) when is_list(Config) ->
{document_root, PrivDir},
{bind_address, "localhost"}],
- inets:enable_trace(max, io),
-
i("httpd_reload -> start inets"),
ok = inets:start(),
diff --git a/lib/inets/test/inets_appup_test.erl b/lib/inets/test/inets_appup_test.erl
index 7ed237243e..648e373312 100644
--- a/lib/inets/test/inets_appup_test.erl
+++ b/lib/inets/test/inets_appup_test.erl
@@ -257,6 +257,21 @@ check_instruction(_, Instr, _AllInstr, _Modules) ->
check_version(V) when is_list(V) ->
ok;
+check_version(REBin) when is_binary(REBin) ->
+ try
+ begin
+ RE = binary_to_list(REBin),
+ case re:compile(RE) of
+ {ok, _} ->
+ ok;
+ {error, _} ->
+ error({bad_version, REBin})
+ end
+ end
+ catch
+ _T:_E ->
+ error({bad_version, REBin})
+ end;
check_version(V) ->
error({bad_version, V}).
diff --git a/lib/inets/test/inets_sup_SUITE.erl b/lib/inets/test/inets_sup_SUITE.erl
index 1d262a2739..12b85a816f 100644
--- a/lib/inets/test/inets_sup_SUITE.erl
+++ b/lib/inets/test/inets_sup_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -21,7 +21,7 @@
-module(inets_sup_SUITE).
-include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
+
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -226,8 +226,6 @@ ftpc_worker(doc) ->
ftpc_worker(suite) ->
[];
ftpc_worker(Config) when is_list(Config) ->
- inets:disable_trace(),
- inets:enable_trace(max, io, ftpc),
[] = supervisor:which_children(ftp_sup),
try
begin
@@ -239,20 +237,16 @@ ftpc_worker(Config) when is_list(Config) ->
inets:stop(ftpc, Pid),
test_server:sleep(5000),
[] = supervisor:which_children(ftp_sup),
- inets:disable_trace(),
ok;
Children ->
- inets:disable_trace(),
exit({unexpected_children, Children})
end;
_ ->
- inets:disable_trace(),
{skip, "Unable to reach test FTP server"}
end
end
catch
throw:{error, not_found} ->
- inets:disable_trace(),
{skip, "No available FTP servers"}
end.
@@ -303,13 +297,14 @@ httpd_subtree(Config) when is_list(Config) ->
%% Check that we have the expected httpd instance children
io:format("httpd_subtree -> verify httpd instance children "
"(acceptor, misc and manager)~n", []),
+ {ok, _} = verify_child(Instance, httpd_connection_sup, supervisor),
{ok, _} = verify_child(Instance, httpd_acceptor_sup, supervisor),
{ok, _} = verify_child(Instance, httpd_misc_sup, supervisor),
{ok, _} = verify_child(Instance, httpd_manager, worker),
%% Check that the httpd instance acc supervisor has children
io:format("httpd_subtree -> verify acc~n", []),
- InstanceAcc = httpd_util:make_name("httpd_acc_sup", Addr, Port),
+ InstanceAcc = httpd_util:make_name("httpd_acceptor_sup", Addr, Port),
case supervisor:which_children(InstanceAcc) of
[_ | _] ->
ok;
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index 0f8671b682..b60a2fb30b 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,26 +22,8 @@
-include("inets_test_lib.hrl").
-include_lib("inets/src/http_lib/http_internal.hrl").
-%% Various small utility functions
--export([start_http_server/1, start_http_server/2]).
--export([start_http_server_ssl/1, start_http_server_ssl/2]).
--export([hostname/0]).
--export([connect_bin/3, connect_bin/4,
- connect_byte/3, connect_byte/4,
- send/3, close/2]).
--export([copy_file/3, copy_files/2, copy_dirs/2, del_dirs/1]).
--export([info/4, log/4, debug/4, print/4]).
--export([timestamp/0, formated_timestamp/0]).
--export([tsp/1, tsp/2, tsf/1, tss/1]).
--export([check_body/1]).
--export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]).
--export([oscmd/1, has_ipv6_support/0, has_ipv6_support/1, print_system_info/1]).
--export([run_on_os/2, run_on_windows/1]).
--export([ensure_started/1]).
--export([non_pc_tc_maybe_skip/4, os_based_skip/1, skip/3, fail/3]).
--export([flush/0]).
--export([start_node/1, stop_node/1]).
-
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
%% -- Misc os command and stuff
@@ -305,7 +287,9 @@ print(F, A, Mod, Line) ->
print("", F, A, Mod, Line).
hostname() ->
- from($@, atom_to_list(node())).
+ {ok, Name} = inet:gethostname(),
+ Name.
+
from(H, [H | T]) -> T;
from(H, [_ | T]) -> from(H, T);
from(_, []) -> [].
@@ -474,7 +458,7 @@ connect_bin(ssl, Host, Port, Opts0) ->
Opts = [binary, {packet,0} | Opts0],
connect(ssl, Host, Port, Opts);
connect_bin(essl, Host, Port, Opts0) ->
- Opts = [{ssl_imp, new}, binary, {packet,0}, {reuseaddr, true} | Opts0],
+ Opts = [{ssl_imp, new}, binary, {packet,0}| Opts0],
connect(ssl, Host, Port, Opts);
connect_bin(ip_comm, Host, Port, Opts0) ->
Opts = [binary, {packet, 0} | Opts0],
@@ -494,74 +478,10 @@ connect_byte(ip_comm, Host, Port, Opts0) ->
Opts = [{packet,0} | Opts0],
connect(ip_comm, Host, Port, Opts).
-
-%% This always falls back on IPV4, but tries IPV6 first.
-connect(Proto, Host, Port, Opts0) ->
- Opts = Opts0 -- [inet, inet6],
- connect(Proto, Host, Port, Opts ++ [inet6], inet6).
-
-connect(ssl, Host, Port, Opts, Type) ->
- tsp("connect(ssl) -> entry with"
- "~n Host: ~p"
- "~n Port: ~p"
- "~n Opts: ~p"
- "~n Type: ~p", [Host, Port, Opts, Type]),
- ssl:start(),
- %% We ignore this option for ssl...
- %% ...maybe we should really treat this in the same way as ip_comm...
- case ssl:connect(Host, Port, Opts) of
- {ok, Socket} ->
- {ok, Socket};
- {error, Reason} when Type =:= inet6 ->
- tsp("connect(ssl) -> failed connecting with inet6: "
- "~n Reason: ~p"
- "~n trying inet", [Reason]),
- connect(ssl, Host, Port, Opts -- [inet6], inet);
- {error, Reason} ->
- tsp("connect(ssl) -> failed connecting: "
- "~n Reason: ~p", [Reason]),
- {error, Reason};
- Error ->
- Error
- end;
-connect(ip_comm, Host, Port, Opts, Type) ->
- tsp("connect(ip_comm) -> entry with"
- "~n Host: ~p"
- "~n Port: ~p"
- "~n Opts: ~p"
- "~n Type: ~p", [Host, Port, Opts, Type]),
-
- case gen_tcp:connect(Host, Port, Opts, timer:seconds(10)) of
- {ok, Socket} ->
- tsp("connect success"),
- {ok, Socket};
-
- {error, Reason} when ((Type =:= inet6) andalso
- ((Reason =:= timeout) orelse
- (Reason =:= nxdomain) orelse
- (Reason =:= eafnosupport) orelse
- (Reason =:= econnreset) orelse
- (Reason =:= enetunreach) orelse
- (Reason =:= econnrefused) orelse
- (Reason =:= ehostunreach))) ->
- tsp("connect(ip_comm) -> Connect error: "
- "~n Reason: ~p"
- "~n Type: ~p"
- "~n Opts: ~p", [Reason, Type, Opts]),
- connect(ip_comm, Host, Port, Opts -- [inet6], inet);
-
- Error ->
- tsp("connect(ip_comm) -> Fatal connect error: "
- "~n Error: ~p"
- "~nwhen"
- "~n Host: ~p"
- "~n Port: ~p"
- "~n Opts: ~p"
- "~n Type: ~p"
- "~n", [Error, Host, Port, Opts, Type]),
- Error
- end.
-
+connect(ip_comm, Host, Port, Opts) ->
+ gen_tcp:connect(Host, Port, Opts);
+connect(ssl, Host, Port, Opts) ->
+ ssl:connect(Host, Port, Opts).
send(ssl, Socket, Data) ->
ssl:send(Socket, Data);
@@ -627,14 +547,14 @@ tsp(F) ->
tsp(F, []).
tsp(F, A) ->
Timestamp = formated_timestamp(),
- test_server:format("*** ~s ~p ~p " ++ F ++ "~n",
+ ct:pal("*** ~s ~p ~p " ++ F ++ "~n",
[Timestamp, node(), self() | A]).
tsf(Reason) ->
- test_server:fail(Reason).
+ ct:fail(Reason).
tss(Time) ->
- test_server:sleep(Time).
+ ct:sleep(Time).
timestamp() ->
http_util:timestamp().
@@ -651,3 +571,12 @@ format_timestamp({_N1, _N2, N3} = Now) ->
[YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
lists:flatten(FormatDate).
+start_apps(Apps) ->
+ lists:foreach(fun(App) ->
+ application:stop(App),
+ application:start(App)
+ end, Apps).
+stop_apps(Apps) ->
+ lists:foreach(fun(App) ->
+ application:stop(App)
+ end, Apps).
diff --git a/lib/inets/test/old_httpc_SUITE.erl b/lib/inets/test/old_httpc_SUITE.erl
new file mode 100644
index 0000000000..3d7de71052
--- /dev/null
+++ b/lib/inets/test/old_httpc_SUITE.erl
@@ -0,0 +1,3602 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%
+%% ts:run(inets, httpc_SUITE, [batch]).
+%%
+
+-module(old_httpc_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include("test_server_line.hrl").
+
+-include_lib("kernel/include/file.hrl").
+-include("inets_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+%% Test server specific exports
+-define(IP_PORT, 8998).
+-define(SSL_PORT, 8999).
+-define(NOT_IN_USE_PORT, 8997).
+-define(LOCAL_HOST, {127,0,0,1}).
+-define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1").
+-define(URL_START, "http://localhost:").
+-define(SSL_URL_START, "https://localhost:").
+-define(CR, $\r).
+-define(LF, $\n).
+-define(HTTP_MAX_HEADER_SIZE, 10240).
+
+
+%%--------------------------------------------------------------------
+%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
+%% Arg - doc | suite
+%% Doc - string()
+%% Case - atom()
+%% Name of a test case function.
+%% Comment - string()
+%% Description: Returns documentation/test cases in this test suite
+%% or a skip tuple if the platform is not supported.
+%%--------------------------------------------------------------------
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ http_options,
+ %% http_head,
+ %% http_get,
+ %%http_post,
+ %%http_post_streaming,
+ %% http_dummy_pipe,
+ %% http_inets_pipe,
+ %% http_trace,
+ %% http_async,
+ %% http_save_to_file,
+ %% http_save_to_file_async,
+ %%http_headers,
+ %%http_headers_dummy,
+
+ %%http_bad_response,
+
+ http_redirect,
+ http_redirect_loop,
+
+ %%http_internal_server_error,
+ %%http_userinfo,
+
+ %%http_cookie,
+ %%http_server_does_not_exist,
+ %%http_invalid_http,
+ %%http_emulate_lower_versions,
+ %%http_relaxed,
+ %%page_does_not_exist,
+ %%parse_url,
+ options,
+ %%headers_as_is,
+ selecting_session,
+
+ %%{group, ssl},
+ %%{group, stream},
+ {group, ipv6},
+ {group, tickets},
+ initial_server_connect
+ ].
+
+groups() ->
+ [
+ %% {ssl, [], [ssl_head,
+ %% essl_head,
+ %% ssl_get,
+ %% essl_get,
+ %% ssl_trace,
+ %% essl_trace]},
+ %% {stream, [], [http_stream,
+ %% http_stream_once]},
+ {tickets, [], [%%hexed_query_otp_6191,
+ %%empty_body_otp_6243,
+ %%empty_response_header_otp_6830,
+ %%transfer_encoding_otp_6807,
+ %%no_content_204_otp_6982,
+ %%missing_CR_otp_7304,
+ %% {group, otp_7883},
+ %% {group, otp_8154},
+ %% {group, otp_8106},
+ otp_8056,
+ otp_8352,
+ otp_8371,
+ otp_8739]},
+ %% {otp_7883, [], [otp_7883_1,
+ %% otp_7883_2]},
+ {otp_8154, [], [otp_8154_1]},
+ %%{otp_8106, [], [otp_8106_pid,
+ %% otp_8106_fun,
+ %% otp_8106_mfa]},
+ {ipv6, [], [ipv6_ipcomm, ipv6_essl]}
+ ].
+
+
+init_per_group(ipv6 = _GroupName, Config) ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
+ Config;
+ _ ->
+ {skip, "Host does not support IPv6"}
+ end;
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initiation before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+
+ ?PRINT_SYSTEM_INFO([]),
+
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ ServerRoot = filename:join(PrivDir, "server_root"),
+ DocRoot = filename:join(ServerRoot, "htdocs"),
+ IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
+ SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
+
+ setup_server_dirs(ServerRoot, DocRoot, DataDir),
+ create_config(IpConfFile, ip_comm, ?IP_PORT, PrivDir, ServerRoot,
+ DocRoot, DataDir),
+ create_config(SslConfFile, ssl, ?SSL_PORT, PrivDir, ServerRoot,
+ DocRoot, DataDir),
+
+ Cgi = case test_server:os_type() of
+ {win32, _} ->
+ filename:join([ServerRoot, "cgi-bin", "cgi_echo.exe"]);
+ _ ->
+ filename:join([ServerRoot, "cgi-bin", "cgi_echo"])
+ end,
+
+ {ok, FileInfo} = file:read_file_info(Cgi),
+ ok = file:write_file_info(Cgi, FileInfo#file_info{mode = 8#00755}),
+
+ [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
+ {server_root, ServerRoot},
+ {doc_root, DocRoot},
+ {local_port, ?IP_PORT},
+ {local_ssl_port, ?SSL_PORT} | Config].
+
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ inets_test_lib:del_dirs(PrivDir),
+ application:stop(inets),
+ application:stop(ssl),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(Case, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initiation before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+
+init_per_testcase(otp_8154_1 = Case, Config) ->
+ init_per_testcase(Case, 5, Config);
+
+init_per_testcase(initial_server_connect = Case, Config) ->
+ %% Try to check if crypto actually exist or not,
+ %% this test case does not work unless it does
+ try
+ begin
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
+ inets:start(),
+ Config
+ end
+ catch
+ throw:{error, {failed_starting, App, ActualError}} ->
+ tsp("init_per_testcase(~w) -> failed starting ~w: "
+ "~n ~p", [Case, App, ActualError]),
+ SkipString =
+ "Could not start " ++ atom_to_list(App),
+ skip(SkipString);
+ _:X ->
+ SkipString =
+ lists:flatten(
+ io_lib:format("Failed starting apps: ~p", [X])),
+ skip(SkipString)
+ end;
+
+init_per_testcase(Case, Config) ->
+ init_per_testcase(Case, 2, Config).
+
+init_per_testcase(Case, Timeout, Config) ->
+ io:format(user,
+ "~n~n*** INIT ~w:~w[~w] ***"
+ "~n~n", [?MODULE, Case, Timeout]),
+
+ PrivDir = ?config(priv_dir, Config),
+ application:stop(inets),
+ Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
+ TmpConfig = lists:keydelete(watchdog, 1, Config),
+ IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
+ SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
+
+ %% inets:enable_trace(max, io, httpd),
+ %% inets:enable_trace(max, io, httpc),
+ %% inets:enable_trace(max, io, all),
+
+ NewConfig =
+ case atom_to_list(Case) of
+ [$s, $s, $l | _] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
+ init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
+ [{watchdog, Dog} | TmpConfig]);
+
+ [$e, $s, $s, $l | _] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
+ init_per_testcase_ssl(essl, PrivDir, SslConfFile,
+ [{watchdog, Dog} | TmpConfig]);
+
+ "ipv6_" ++ _Rest ->
+ %% Ensure needed apps (crypto, public_key and ssl) are started
+ try ?ENSURE_STARTED([crypto, public_key, ssl]) of
+ ok ->
+ Profile = ipv6,
+ %% A stand-alone profile is represented by a pid()
+ {ok, ProfilePid} =
+ inets:start(httpc,
+ [{profile, Profile},
+ {data_dir, PrivDir}], stand_alone),
+ ok = httpc:set_options([{ipfamily, inet6}],
+ ProfilePid),
+ tsp("httpc profile pid: ~p", [ProfilePid]),
+ [{watchdog, Dog}, {profile, ProfilePid}| TmpConfig]
+ catch
+ throw:{error, {failed_starting, App, ActualError}} ->
+ tsp("init_per_testcase(~w) -> failed starting ~w: "
+ "~n ~p", [Case, App, ActualError]),
+ SkipString =
+ "Could not start " ++ atom_to_list(App),
+ skip(SkipString);
+ _:X ->
+ SkipString =
+ lists:flatten(
+ io_lib:format("Failed starting apps: ~p", [X])),
+ skip(SkipString)
+ end;
+
+ _ ->
+ %% Try inet6fb4 on windows...
+ %% No need? Since it is set above?
+
+ %% tsp("init_per_testcase -> allways try IPv6 on windows"),
+ %% ?RUN_ON_WINDOWS(
+ %% fun() ->
+ %% tsp("init_per_testcase:set_options_fun -> "
+ %% "set-option ipfamily to inet6fb4"),
+ %% Res = httpc:set_options([{ipfamily, inet6fb4}]),
+ %% tsp("init_per_testcase:set_options_fun -> "
+ %% "~n Res: ~p", [Res]),
+ %% Res
+ %% end),
+
+ TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
+ %% Will start inets
+ tsp("init_per_testcase -> try start server"),
+ Server = start_http_server(PrivDir, IpConfFile),
+ [{watchdog, Dog}, {local_server, Server} | TmpConfig2]
+ end,
+
+ %% <IPv6>
+ %% Set default ipfamily to the same as the main server has by default
+ %% This makes the client try w/ ipv6 before falling back to ipv4,
+ %% as that is what the server is configured to do.
+ %% Note that this is required for the tests to run on *BSD w/ ipv6 enabled
+ %% as well as on Windows. The Linux behaviour of allowing ipv4 connects
+ %% to ipv6 sockets is not required or even encouraged.
+
+ tsp("init_per_testcase -> Options before ipfamily set: ~n~p",
+ [httpc:get_options(all)]),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("init_per_testcase -> Options after ipfamily set: ~n~p",
+ [httpc:get_options(all)]),
+
+ %% Note that the IPv6 test case(s) *must* use inet6,
+ %% so this value will be overwritten (see "ipv6_" below).
+ %% </IPv6>
+
+ %% inets:enable_trace(max, io, all),
+ %% snmp:set_trace([gen_tcp]),
+ tsp("init_per_testcase(~w) -> done when"
+ "~n NewConfig: ~p"
+ "~n~n", [Case, NewConfig]),
+ NewConfig.
+
+
+init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
+ tsp("init_per_testcase_ssl(~w) -> stop ssl", [Tag]),
+ application:stop(ssl),
+ Config2 = lists:keydelete(local_ssl_server, 1, Config),
+ %% Will start inets
+ tsp("init_per_testcase_ssl(~w) -> try start http server (including inets)",
+ [Tag]),
+ Server = inets_test_lib:start_http_server(
+ filename:join(PrivDir, SslConfFile), Tag),
+ tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
+ [{local_ssl_server, Server} | Config2].
+
+start_http_server(ConfDir, ConfFile) ->
+ inets_test_lib:start_http_server( filename:join(ConfDir, ConfFile) ).
+
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(Case, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(http_save_to_file = Case, Config) ->
+ io:format(user, "~n~n*** END ~w:~w ***~n~n",
+ [?MODULE, Case]),
+ PrivDir = ?config(priv_dir, Config),
+ FullPath = filename:join(PrivDir, "dummy.html"),
+ file:delete(FullPath),
+ finish(Config);
+
+end_per_testcase(Case, Config) ->
+ io:format(user, "~n~n*** END ~w:~w ***~n~n",
+ [?MODULE, Case]),
+ case atom_to_list(Case) of
+ "ipv6_" ++ _Rest ->
+ tsp("end_per_testcase(~w) -> stop ssl", [Case]),
+ application:stop(ssl),
+ tsp("end_per_testcase(~w) -> stop public_key", [Case]),
+ application:stop(public_key),
+ tsp("end_per_testcase(~w) -> stop crypto", [Case]),
+ application:stop(crypto),
+ ProfilePid = ?config(profile, Config),
+ tsp("end_per_testcase(~w) -> stop httpc profile (~p)",
+ [Case, ProfilePid]),
+ unlink(ProfilePid),
+ inets:stop(stand_alone, ProfilePid),
+ tsp("end_per_testcase(~w) -> httpc profile (~p) stopped",
+ [Case, ProfilePid]),
+ ok;
+ _ ->
+ ok
+ end,
+ finish(Config).
+
+finish(Config) ->
+ Dog = ?config(watchdog, Config),
+ case Dog of
+ undefined ->
+ ok;
+ _ ->
+ tsp("finish -> stop watchdog (~p)", [Dog]),
+ test_server:timetrap_cancel(Dog)
+ end.
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
+
+
+
+%%-------------------------------------------------------------------------
+
+http_options(doc) ->
+ ["Test http options request against local server."];
+http_options(suite) ->
+ [];
+http_options(Config) when is_list(Config) ->
+ skip("Not supported by httpd").
+
+http_head(doc) ->
+ ["Test http head request against local server."];
+http_head(suite) ->
+ [];
+http_head(Config) when is_list(Config) ->
+ tsp("http_head -> entry with"
+ "~n Config: ~p", [Config]),
+ Method = head,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HttpOpts = [],
+ Opts = [],
+ VerifyResult =
+ fun({ok, {{_,200,_}, [_ | _], []}}) ->
+ ok;
+ ({ok, UnexpectedReply}) ->
+ tsp("http_head:verify_fun -> Unexpected Reply: "
+ "~n ~p", [UnexpectedReply]),
+ tsf({unexpected_reply, UnexpectedReply});
+ ({error, Reason} = Error) ->
+ tsp("http_head:verify_fun -> Error reply: "
+ "~n Reason: ~p", [Reason]),
+ tsf({bad_reply, Error})
+ end,
+ simple_request_and_verify(Config,
+ Method, Request, HttpOpts, Opts, VerifyResult).
+
+
+%%-------------------------------------------------------------------------
+
+http_get(doc) ->
+ ["Test http get request against local server"];
+http_get(suite) ->
+ [];
+http_get(Config) when is_list(Config) ->
+ tsp("http_get -> entry with"
+ "~n Config: ~p", [Config]),
+ case ?config(local_server, Config) of
+ ok ->
+ tsp("local-server running"),
+ Method = get,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ Timeout = timer:seconds(1),
+ ConnTimeout = Timeout + timer:seconds(1),
+ HttpOptions1 = [{timeout, Timeout},
+ {connect_timeout, ConnTimeout}],
+ Options1 = [],
+ Body =
+ case httpc:request(Method, Request, HttpOptions1, Options1) of
+ {ok, {{_,200,_}, [_ | _], ReplyBody = [_ | _]}} ->
+ ReplyBody;
+ {ok, UnexpectedReply1} ->
+ tsf({unexpected_reply, UnexpectedReply1});
+ {error, _} = Error1 ->
+ tsf({bad_reply, Error1})
+ end,
+
+ %% eqvivivalent to httpc:request(get, {URL, []}, [], []),
+ inets_test_lib:check_body(Body),
+
+ HttpOptions2 = [],
+ Options2 = [{body_format, binary}],
+ case httpc:request(Method, Request, HttpOptions2, Options2) of
+ {ok, {{_,200,_}, [_ | _], Bin}} when is_binary(Bin) ->
+ ok;
+ {ok, {{_,200,_}, [_ | _], BadBin}} ->
+ tsf({body_format_not_binary, BadBin});
+ {ok, UnexpectedReply2} ->
+ tsf({unexpected_reply, UnexpectedReply2});
+ {error, _} = Error2 ->
+ tsf({bad_reply, Error2})
+ end;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+%%-------------------------------------------------------------------------
+
+http_post(doc) ->
+ ["Test http post request against local server. We do in this case "
+ "only care about the client side of the the post. The server "
+ "script will not actually use the post data."];
+http_post(suite) ->
+ [];
+http_post(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+
+ URL = case test_server:os_type() of
+ {win32, _} ->
+ ?URL_START ++ integer_to_list(Port) ++
+ "/cgi-bin/cgi_echo.exe";
+ _ ->
+ ?URL_START ++ integer_to_list(Port) ++
+ "/cgi-bin/cgi_echo"
+
+ end,
+ %% Cgi-script expects the body length to be 100
+ Body = lists:duplicate(100, "1"),
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(post, {URL, [{"expect","100-continue"}],
+ "text/plain", Body}, [], []),
+
+ {ok, {{_,504,_}, [_ | _], []}} =
+ httpc:request(post, {URL, [{"expect","100-continue"}],
+ "text/plain", "foobar"}, [], []);
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+%%-------------------------------------------------------------------------
+http_post_streaming(doc) ->
+ ["Test streaming http post request against local server. "
+ "We only care about the client side of the the post. "
+ "The server script will not actually use the post data."];
+http_post_streaming(suite) ->
+ [];
+http_post_streaming(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = case test_server:os_type() of
+ {win32, _} ->
+ ?URL_START ++ integer_to_list(Port) ++
+ "/cgi-bin/cgi_echo.exe";
+ _ ->
+ ?URL_START ++ integer_to_list(Port) ++
+ "/cgi-bin/cgi_echo"
+ end,
+ %% Cgi-script expects the body length to be 100
+ BodyFun = fun(0) ->
+ io:format("~w:http_post_streaming_fun -> "
+ "zero~n", [?MODULE]),
+ eof;
+ (LenLeft) ->
+ io:format("~w:http_post_streaming_fun -> "
+ "LenLeft: ~p~n", [?MODULE, LenLeft]),
+ {ok, lists:duplicate(10, "1"), LenLeft - 10}
+ end,
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(post, {URL,
+ [{"expect", "100-continue"},
+ {"content-length", "100"}],
+ "text/plain", {BodyFun, 100}}, [], []),
+
+ {ok, {{_,504,_}, [_ | _], []}} =
+ httpc:request(post, {URL,
+ [{"expect", "100-continue"},
+ {"content-length", "10"}],
+ "text/plain", {BodyFun, 10}}, [], []);
+
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+%%-------------------------------------------------------------------------
+http_emulate_lower_versions(doc) ->
+ ["Perform request as 0.9 and 1.0 clients."];
+http_emulate_lower_versions(suite) ->
+ [];
+http_emulate_lower_versions(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, Body0} =
+ httpc:request(get, {URL, []}, [{version, "HTTP/0.9"}], []),
+ inets_test_lib:check_body(Body0),
+ {ok, {{"HTTP/1.0", 200, _}, [_ | _], Body1 = [_ | _]}} =
+ httpc:request(get, {URL, []}, [{version, "HTTP/1.0"}], []),
+ inets_test_lib:check_body(Body1),
+ {ok, {{"HTTP/1.1", 200, _}, [_ | _], Body2 = [_ | _]}} =
+ httpc:request(get, {URL, []}, [{version, "HTTP/1.1"}], []),
+ inets_test_lib:check_body(Body2);
+ _->
+ skip("Failed to start local http-server")
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+http_relaxed(doc) ->
+ ["Test relaxed mode"];
+http_relaxed(suite) ->
+ [];
+http_relaxed(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
+ %% ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++
+ "/missing_reason_phrase.html",
+
+ {error, Reason} =
+ httpc:request(get, {URL, []}, [{relaxed, false}], []),
+
+ test_server:format("Not relaxed: ~p~n", [Reason]),
+
+ {ok, {{_, 200, _}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, []}, [{relaxed, true}], []),
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipv6, enabled}]),
+ %% ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+http_dummy_pipe(doc) ->
+ ["Test pipelining code."];
+http_dummy_pipe(suite) ->
+ [];
+http_dummy_pipe(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/foobar.html",
+
+ test_pipeline(URL),
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+http_inets_pipe(doc) ->
+ ["Test pipelining code."];
+http_inets_pipe(suite) ->
+ [];
+http_inets_pipe(Config) when is_list(Config) ->
+
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ test_pipeline(URL);
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+test_pipeline(URL) ->
+ p("test_pipeline -> entry with"
+ "~n URL: ~p", [URL]),
+
+ httpc:set_options([{pipeline_timeout, 50000},
+ {max_pipeline_length, 5}]),
+
+ p("test_pipeline -> issue (async) request 1"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdA1} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdA1: ~p", [RequestIdA1]),
+ p("test_pipeline -> RequestIdA1: ~p"
+ "~n when profile info: ~p", [RequestIdA1, httpc:info()]),
+
+ %% Make sure pipeline is initiated
+ p("test_pipeline -> sleep some", []),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request A2, A3 and A4"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdA2} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdA3} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdA4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p",
+ [RequestIdA2, RequestIdA3, RequestIdA4]),
+ p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p"
+ "~n when profile info: ~p",
+ [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]),
+
+ p("test_pipeline -> issue (sync) request 3"),
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, []}, [], []),
+
+ p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4"
+ "~n when profile info: ~p", [httpc:info()]),
+ pipeline_await_async_reply([{RequestIdA1, a1, 200},
+ {RequestIdA2, a2, 200},
+ {RequestIdA3, a3, 200},
+ {RequestIdA4, a4, 200}], ?MINS(2)),
+
+ p("test_pipeline -> sleep some"
+ "~n when profile info: ~p", [httpc:info()]),
+ test_server:sleep(4000),
+
+ p("test_pipeline -> issue (async) request B1, B2, B3 and B4"
+ "~n when profile info: ~p", [httpc:info()]),
+ {ok, RequestIdB1} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdB2} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdB3} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ {ok, RequestIdB4} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p",
+ [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]),
+ p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p"
+ "~n when profile info: ~p",
+ [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]),
+
+ p("test_pipeline -> cancel (async) request B2"
+ "~n when profile info: ~p", [httpc:info()]),
+ ok = httpc:cancel_request(RequestIdB2),
+
+ p("test_pipeline -> "
+ "expect *no* reply for cancelled (async) request B2 (for 3 secs)"
+ "~n when profile info: ~p", [httpc:info()]),
+ receive
+ {http, {RequestIdB2, _}} ->
+ tsf(http_cancel_request_failed)
+ after 3000 ->
+ ok
+ end,
+
+ p("test_pipeline -> expect reply for (async) request B1, B3 and B4"
+ "~n when profile info: ~p", [httpc:info()]),
+ Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200},
+ {RequestIdB3, b3, 200},
+ {RequestIdB4, b4, 200}], ?MINS(1)),
+ [{b1, Body}|_] = Bodies,
+
+ p("test_pipeline -> check reply for (async) request B1"
+ "~n when profile info: ~p", [httpc:info()]),
+ inets_test_lib:check_body(binary_to_list(Body)),
+
+ p("test_pipeline -> ensure no unexpected incomming"
+ "~n when profile info: ~p", [httpc:info()]),
+ receive
+ {http, Any} ->
+ tsf({unexpected_message, Any})
+ after 500 ->
+ ok
+ end,
+
+ p("test_pipeline -> done"
+ "~n when profile info: ~p", [httpc:info()]),
+ ok.
+
+pipeline_await_async_reply(ReqIds, Timeout) ->
+ pipeline_await_async_reply(ReqIds, Timeout, []).
+
+pipeline_await_async_reply([], _, Acc) ->
+ lists:keysort(1, Acc);
+pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 ->
+ T1 = inets_test_lib:timestamp(),
+ p("pipeline_await_async_reply -> await replies"
+ "~n ReqIds: ~p"
+ "~n Timeout: ~p", [ReqIds, Timeout]),
+ receive
+ {http, {RequestId, {{_, Status, _}, _, Body}}} ->
+ p("pipeline_await_async_reply -> received reply for"
+ "~n RequestId: ~p"
+ "~n Status: ~p", [RequestId, Status]),
+ case lists:keysearch(RequestId, 1, ReqIds) of
+ {value, {RequestId, N, Status}} ->
+ p("pipeline_await_async_reply -> "
+ "found expected request ~w", [N]),
+ ReqIds2 = lists:keydelete(RequestId, 1, ReqIds),
+ NewTimeout = Timeout - (inets_test_lib:timestamp()-T1),
+ pipeline_await_async_reply(ReqIds2, NewTimeout,
+ [{N, Body} | Acc]);
+ {value, {RequestId, N, WrongStatus}} ->
+ p("pipeline_await_async_reply -> "
+ "found request ~w with wrong status", [N]),
+ tsf({reply_with_unexpected_status,
+ {RequestId, N, WrongStatus}});
+ false ->
+ tsf({unexpected_reply, {RequestId, Status}})
+ end;
+ {http, Msg} ->
+ tsf({unexpected_reply, Msg})
+ after Timeout ->
+ receive
+ Any ->
+ tsp("pipeline_await_async_reply -> "
+ "received unknown data after timeout: "
+ "~n ~p", [Any]),
+ tsf({timeout, {unknown, Any}})
+ end
+ end;
+pipeline_await_async_reply(ReqIds, _, Acc) ->
+ tsp("pipeline_await_async_reply -> "
+ "timeout: "
+ "~n ~p"
+ "~nwhen"
+ "~n ~p", [ReqIds, Acc]),
+ tsf({timeout, ReqIds, Acc}).
+
+
+
+%%-------------------------------------------------------------------------
+http_trace(doc) ->
+ ["Perform a TRACE request."];
+http_trace(suite) ->
+ [];
+http_trace(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ case httpc:request(trace, {URL, []}, [], []) of
+ {ok, {{_,200,_}, [_ | _], "TRACE /dummy.html" ++ _}} ->
+ ok;
+ {ok, {{_,200,_}, [_ | _], WrongBody}} ->
+ tsf({wrong_body, WrongBody});
+ {ok, WrongReply} ->
+ tsf({wrong_reply, WrongReply});
+ Error ->
+ tsf({failed, Error})
+ end;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+%%-------------------------------------------------------------------------
+http_async(doc) ->
+ ["Test an asynchrony http request."];
+http_async(suite) ->
+ [];
+http_async(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, RequestId} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+
+ Body =
+ receive
+ {http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
+ BinBody;
+ {http, Msg} ->
+ tsf(Msg)
+ end,
+
+ inets_test_lib:check_body(binary_to_list(Body)),
+
+ {ok, NewRequestId} =
+ httpc:request(get, {URL, []}, [], [{sync, false}]),
+ ok = httpc:cancel_request(NewRequestId),
+ receive
+ {http, {NewRequestId, _NewResult}} ->
+ tsf(http_cancel_request_failed)
+ after 3000 ->
+ ok
+ end;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+%%-------------------------------------------------------------------------
+http_save_to_file(doc) ->
+ ["Test to save the http body to a file"];
+http_save_to_file(suite) ->
+ [];
+http_save_to_file(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ PrivDir = ?config(priv_dir, Config),
+ FilePath = filename:join(PrivDir, "dummy.html"),
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, saved_to_file}
+ = httpc:request(get, {URL, []}, [], [{stream, FilePath}]),
+ {ok, Bin} = file:read_file(FilePath),
+ {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
+ Bin == Body;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+%%-------------------------------------------------------------------------
+http_save_to_file_async(doc) ->
+ ["Test to save the http body to a file"];
+http_save_to_file_async(suite) ->
+ [];
+http_save_to_file_async(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ PrivDir = ?config(priv_dir, Config),
+ FilePath = filename:join(PrivDir, "dummy.html"),
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, RequestId} = httpc:request(get, {URL, []}, [],
+ [{stream, FilePath},
+ {sync, false}]),
+ receive
+ {http, {RequestId, saved_to_file}} ->
+ ok;
+ {http, Msg} ->
+ tsf(Msg)
+ end,
+
+ {ok, Bin} = file:read_file(FilePath),
+ {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
+ Bin == Body;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+%%-------------------------------------------------------------------------
+http_headers(doc) ->
+ ["Use as many request headers as possible not used in proxy_headers"];
+http_headers(suite) ->
+ [];
+http_headers(Config) when is_list(Config) ->
+
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ DocRoot = ?config(doc_root, Config),
+ {ok, FileInfo} =
+ file:read_file_info(filename:join([DocRoot,"dummy.html"])),
+ CreatedSec =
+ calendar:datetime_to_gregorian_seconds(
+ FileInfo#file_info.mtime),
+
+ Mod = httpd_util:rfc1123_date(
+ calendar:gregorian_seconds_to_datetime(
+ CreatedSec-1)),
+
+ Date = httpd_util:rfc1123_date({date(), time()}),
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, [{"If-Modified-Since",
+ Mod},
+ {"From","[email protected]"},
+ {"Date", Date}
+ ]}, [], []),
+
+ Mod1 = httpd_util:rfc1123_date(
+ calendar:gregorian_seconds_to_datetime(
+ CreatedSec+1)),
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, [{"If-UnModified-Since",
+ Mod1}
+ ]}, [], []),
+
+ Tag = httpd_util:create_etag(FileInfo),
+
+
+ {ok, {{_,200,_}, [_ | _], [_ | _]}} =
+ httpc:request(get, {URL, [{"If-Match",
+ Tag}
+ ]}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], _}} =
+ httpc:request(get, {URL, [{"If-None-Match",
+ "NotEtag,NeihterEtag"},
+ {"Connection", "Close"}
+ ]}, [], []),
+ ok;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+%%-------------------------------------------------------------------------
+http_headers_dummy(doc) ->
+ ["Test the code for handling headers we do not want/can send "
+ "to a real server. Note it is not logical to send"
+ "all of these headers together, we only want to test that"
+ "the code for handling headers will not crash."];
+http_headers_dummy(suite) ->
+ [];
+http_headers_dummy(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy_headers.html",
+
+ Foo = http_chunk:encode("foobar") ++
+ binary_to_list(http_chunk:encode_last()),
+ FooBar = Foo ++ "\r\n\r\nOther:inets_test\r\n\r\n",
+
+ UserPasswd = base64:encode_to_string("Alladin:Sesame"),
+ Auth = "Basic " ++ UserPasswd,
+
+ %% The dummy server will ignore the headers, we only want to test
+ %% that the client header-handling code. This would not
+ %% be a vaild http-request!
+ {ok, {{_,200,_}, [_ | _], [_|_]}} =
+ httpc:request(post,
+ {URL,
+ [{"Via",
+ "1.0 fred, 1.1 nowhere.com (Apache/1.1)"},
+ {"Warning","1#pseudonym foobar"},
+ {"Vary","*"},
+ {"Upgrade","HTTP/2.0"},
+ {"Pragma", "1#no-cache"},
+ {"Cache-Control", "no-cache"},
+ {"Connection", "close"},
+ {"Date", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"Accept", " text/plain; q=0.5, text/html"},
+ {"Accept-Language", "en"},
+ {"Accept-Encoding","chunked"},
+ {"Accept-Charset", "ISO8859-1"},
+ {"Authorization", Auth},
+ {"Expect", "1#100-continue"},
+ {"User-Agent","inets"},
+ {"Transfer-Encoding","chunked"},
+ {"Range", " bytes=0-499"},
+ {"If-Range", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"If-Match", "*"},
+ {"Content-Type", "text/plain"},
+ {"Content-Encoding", "chunked"},
+ {"Content-Length", "6"},
+ {"Content-Language", "en"},
+ {"Content-Location", "http://www.foobar.se"},
+ {"Content-MD5",
+ "104528739076276072743283077410617235478"},
+ {"Content-Range", "bytes 0-499/1234"},
+ {"Allow", "GET"},
+ {"Proxy-Authorization", Auth},
+ {"Expires", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"Upgrade", "HTTP/2.0"},
+ {"Last-Modified", "Sat, 29 Oct 1994 19:43:31 GMT"},
+ {"Trailer","1#User-Agent"}
+ ], "text/plain", FooBar},
+ [], []),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+http_bad_response(doc) ->
+ ["Test what happens when the server does not follow the protocol"];
+http_bad_response(suite) ->
+ [];
+http_bad_response(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_crlf.html",
+
+ URL1 = ?URL_START ++ integer_to_list(Port) ++ "/wrong_statusline.html",
+
+ {error, timeout} = httpc:request(get, {URL, []}, [{timeout, 400}], []),
+
+ {error, Reason} = httpc:request(URL1),
+
+ test_server:format("Wrong Statusline: ~p~n", [Reason]),
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+ssl_head(doc) ->
+ ["Same as http_head/1 but over ssl sockets."];
+ssl_head(suite) ->
+ [];
+ssl_head(Config) when is_list(Config) ->
+ ssl_head(ssl, Config).
+
+essl_head(doc) ->
+ ["Same as http_head/1 but over ssl sockets."];
+essl_head(suite) ->
+ [];
+essl_head(Config) when is_list(Config) ->
+ ssl_head(essl, Config).
+
+ssl_head(SslTag, Config) ->
+ tsp("ssl_head -> entry with"
+ "~n SslTag: ~p"
+ "~n Config: ~p", [SslTag, Config]),
+ case ?config(local_ssl_server, Config) of
+ ok ->
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(local_ssl_port, Config),
+ URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+ SSLConfig =
+ case SslTag of
+ ssl ->
+ SSLOptions;
+ essl ->
+ {essl, SSLOptions}
+ end,
+ tsp("ssl_head -> make request using: "
+ "~n URL: ~p"
+ "~n SslTag: ~p"
+ "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
+ {ok, {{_,200, _}, [_ | _], []}} =
+ httpc:request(head, {URL, []}, [{ssl, SSLConfig}], []);
+ {ok, _} ->
+ skip("local http-server not started");
+ _ ->
+ skip("SSL not started")
+ end.
+
+
+%%-------------------------------------------------------------------------
+ssl_get(doc) ->
+ ["Same as http_get/1 but over ssl sockets."];
+ssl_get(suite) ->
+ [];
+ssl_get(Config) when is_list(Config) ->
+ ssl_get(ssl, Config).
+
+essl_get(doc) ->
+ ["Same as http_get/1 but over ssl sockets."];
+essl_get(suite) ->
+ [];
+essl_get(Config) when is_list(Config) ->
+ ssl_get(essl, Config).
+
+ssl_get(SslTag, Config) when is_list(Config) ->
+ case ?config(local_ssl_server, Config) of
+ ok ->
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(local_ssl_port, Config),
+ URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+ SSLConfig =
+ case SslTag of
+ ssl ->
+ SSLOptions;
+ essl ->
+ {essl, SSLOptions}
+ end,
+ tsp("ssl_get -> make request using: "
+ "~n URL: ~p"
+ "~n SslTag: ~p"
+ "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
+ case httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []) of
+ {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} ->
+ inets_test_lib:check_body(Body),
+ ok;
+ {ok, {StatusLine, Headers, _Body}} ->
+ tsp("ssl_get -> unexpected result: "
+ "~n StatusLine: ~p"
+ "~n Headers: ~p", [StatusLine, Headers]),
+ tsf({unexpected_response, StatusLine, Headers});
+ {error, Reason} ->
+ tsp("ssl_get -> request failed: "
+ "~n Reason: ~p", [Reason]),
+ tsf({request_failed, Reason})
+ end;
+ {ok, _} ->
+ skip("local http-server not started");
+ _ ->
+ skip("SSL not started")
+ end.
+
+
+%%-------------------------------------------------------------------------
+ssl_trace(doc) ->
+ ["Same as http_trace/1 but over ssl sockets."];
+ssl_trace(suite) ->
+ [];
+ssl_trace(Config) when is_list(Config) ->
+ ssl_trace(ssl, Config).
+
+essl_trace(doc) ->
+ ["Same as http_trace/1 but over ssl sockets."];
+essl_trace(suite) ->
+ [];
+essl_trace(Config) when is_list(Config) ->
+ ssl_trace(essl, Config).
+
+ssl_trace(SslTag, Config) when is_list(Config) ->
+ case ?config(local_ssl_server, Config) of
+ ok ->
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(local_ssl_port, Config),
+ URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+ SSLConfig =
+ case SslTag of
+ ssl ->
+ SSLOptions;
+ essl ->
+ {essl, SSLOptions}
+ end,
+ tsp("ssl_trace -> make request using: "
+ "~n URL: ~p"
+ "~n SslTag: ~p"
+ "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
+ case httpc:request(trace, {URL, []}, [{ssl, SSLConfig}], []) of
+ {ok, {{_,200, _}, [_ | _], "TRACE /dummy.html" ++ _}} ->
+ ok;
+ {ok, {{_,200,_}, [_ | _], WrongBody}} ->
+ tsf({wrong_body, WrongBody});
+ {ok, WrongReply} ->
+ tsf({wrong_reply, WrongReply});
+ Error ->
+ tsf({failed, Error})
+ end;
+ {ok, _} ->
+ skip("local http-server not started");
+ _ ->
+ skip("SSL not started")
+ end.
+
+
+%%-------------------------------------------------------------------------
+http_redirect(doc) ->
+ ["Test redirect with dummy server as httpd does not implement"
+ " server redirect"];
+http_redirect(suite) ->
+ [];
+http_redirect(Config) when is_list(Config) ->
+ tsp("http_redirect -> entry with"
+ "~n Config: ~p", [Config]),
+ case ?config(local_server, Config) of
+ ok ->
+ %% tsp("http_redirect -> set ipfamily option to inet"),
+ %% ok = httpc:set_options([{ipfamily, inet}]),
+
+ tsp("http_redirect -> start dummy server inet"),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+ tsp("http_redirect -> server port = ~p", [Port]),
+
+ URL300 = ?URL_START ++ integer_to_list(Port) ++ "/300.html",
+
+ tsp("http_redirect -> issue request 1: "
+ "~n ~p", [URL300]),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL300, []}, [], []),
+
+ tsp("http_redirect -> issue request 2: "
+ "~n ~p", [URL300]),
+ {ok, {{_,300,_}, [_ | _], _}} =
+ httpc:request(get, {URL300, []}, [{autoredirect, false}], []),
+
+ URL301 = ?URL_START ++ integer_to_list(Port) ++ "/301.html",
+
+ tsp("http_redirect -> issue request 3: "
+ "~n ~p", [URL301]),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, []}, [], []),
+
+ tsp("http_redirect -> issue request 4: "
+ "~n ~p", [URL301]),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, []}, [], []),
+
+ tsp("http_redirect -> issue request 5: "
+ "~n ~p", [URL301]),
+ {ok, {{_,301,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, [],"text/plain", "foobar"},
+ [], []),
+
+ URL302 = ?URL_START ++ integer_to_list(Port) ++ "/302.html",
+
+ tsp("http_redirect -> issue request 6: "
+ "~n ~p", [URL302]),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL302, []}, [], []),
+ case httpc:request(get, {URL302, []}, [], []) of
+ {ok, Reply7} ->
+ case Reply7 of
+ {{_,200,_}, [_ | _], [_|_]} ->
+ tsp("http_redirect -> "
+ "expected reply for request 7"),
+ ok;
+ {StatusLine, Headers, Body} ->
+ tsp("http_redirect -> "
+ "unexpected reply for request 7: "
+ "~n StatusLine: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p",
+ [StatusLine, Headers, Body]),
+ tsf({unexpected_reply, Reply7})
+ end;
+ Error7 ->
+ tsp("http_redirect -> "
+ "unexpected result for request 7: "
+ "~n Error7: ~p",
+ [Error7]),
+ tsf({unexpected_result, Error7})
+ end,
+
+ tsp("http_redirect -> issue request 7: "
+ "~n ~p", [URL302]),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL302, []}, [], []),
+
+ tsp("http_redirect -> issue request 8: "
+ "~n ~p", [URL302]),
+ {ok, {{_,302,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL302, [],"text/plain", "foobar"},
+ [], []),
+
+ URL303 = ?URL_START ++ integer_to_list(Port) ++ "/303.html",
+
+ tsp("http_redirect -> issue request 9: "
+ "~n ~p", [URL303]),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL303, []}, [], []),
+
+ tsp("http_redirect -> issue request 10: "
+ "~n ~p", [URL303]),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL303, []}, [], []),
+
+ tsp("http_redirect -> issue request 11: "
+ "~n ~p", [URL303]),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL303, [],"text/plain", "foobar"},
+ [], []),
+
+ URL307 = ?URL_START ++ integer_to_list(Port) ++ "/307.html",
+
+ tsp("http_redirect -> issue request 12: "
+ "~n ~p", [URL307]),
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL307, []}, [], []),
+
+ tsp("http_redirect -> issue request 13: "
+ "~n ~p", [URL307]),
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL307, []}, [], []),
+
+ tsp("http_redirect -> issue request 14: "
+ "~n ~p", [URL307]),
+ {ok, {{_,307,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL307, [],"text/plain", "foobar"},
+ [], []),
+
+ tsp("http_redirect -> stop dummy server"),
+ DummyServerPid ! stop,
+ tsp("http_redirect -> reset ipfamily option (to inet6fb4)"),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("http_redirect -> done"),
+ ok;
+
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+
+%%-------------------------------------------------------------------------
+http_redirect_loop(doc) ->
+ ["Test redirect loop detection"];
+http_redirect_loop(suite) ->
+ [];
+http_redirect_loop(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/redirectloop.html",
+
+ {ok, {{_,300,_}, [_ | _], _}}
+ = httpc:request(get, {URL, []}, [], []),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+%%-------------------------------------------------------------------------
+http_internal_server_error(doc) ->
+ ["Test 50X codes"];
+http_internal_server_error(suite) ->
+ [];
+http_internal_server_error(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL500 = ?URL_START ++ integer_to_list(Port) ++ "/500.html",
+
+ {ok, {{_,500,_}, [_ | _], _}}
+ = httpc:request(get, {URL500, []}, [], []),
+
+
+ URL503 = ?URL_START ++ integer_to_list(Port) ++ "/503.html",
+
+ %% Used to be able to make the service available after retry.
+ ets:new(unavailable, [named_table, public, set]),
+ ets:insert(unavailable, {503, unavailable}),
+
+ {ok, {{_,200, _}, [_ | _], [_|_]}} =
+ httpc:request(get, {URL503, []}, [], []),
+
+ ets:insert(unavailable, {503, long_unavailable}),
+
+ {ok, {{_,503, _}, [_ | _], [_|_]}} =
+ httpc:request(get, {URL503, []}, [], []),
+
+ ets:delete(unavailable),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+http_userinfo(doc) ->
+ ["Test user info e.i. http://user:passwd@host:port/"];
+http_userinfo(suite) ->
+ [];
+http_userinfo(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URLAuth = "http://alladin:sesame@localhost:"
+ ++ integer_to_list(Port) ++ "/userinfo.html",
+
+ {ok, {{_,200,_}, [_ | _], _}}
+ = httpc:request(get, {URLAuth, []}, [], []),
+
+ URLUnAuth = "http://alladin:foobar@localhost:"
+ ++ integer_to_list(Port) ++ "/userinfo.html",
+
+ {ok, {{_,401, _}, [_ | _], _}} =
+ httpc:request(get, {URLUnAuth, []}, [], []),
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+http_cookie(doc) ->
+ ["Test cookies."];
+http_cookie(suite) ->
+ [];
+http_cookie(Config) when is_list(Config) ->
+ ok = httpc:set_options([{cookies, enabled}, {ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URLStart = ?URL_START
+ ++ integer_to_list(Port),
+
+ URLCookie = URLStart ++ "/cookie.html",
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URLCookie, []}, [], []),
+
+ ets:new(cookie, [named_table, public, set]),
+ ets:insert(cookie, {cookies, true}),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URLStart ++ "/", []}, [], []),
+
+ ets:delete(cookie),
+
+ ok = httpc:set_options([{cookies, disabled}]),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+%%-------------------------------------------------------------------------
+http_server_does_not_exist(doc) ->
+ ["Test that we get an error message back when the server "
+ "does note exist."];
+http_server_does_not_exist(suite) ->
+ [];
+http_server_does_not_exist(Config) when is_list(Config) ->
+ {error, _} =
+ httpc:request(get, {"http://localhost:" ++
+ integer_to_list(?NOT_IN_USE_PORT)
+ ++ "/", []},[], []),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+page_does_not_exist(doc) ->
+ ["Test that we get a 404 when the page is not found."];
+page_does_not_exist(suite) ->
+ [];
+page_does_not_exist(Config) when is_list(Config) ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/doesnotexist.html",
+ {ok, {{_,404,_}, [_ | _], [_ | _]}}
+ = httpc:request(get, {URL, []}, [], []),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+http_stream(doc) ->
+ ["Test the option stream for asynchrony requests"];
+http_stream(suite) ->
+ [];
+http_stream(Config) when is_list(Config) ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, {{_,200,_}, [_ | _], Body}} =
+ httpc:request(get, {URL, []}, [], []),
+
+ {ok, RequestId} =
+ httpc:request(get, {URL, []}, [], [{sync, false},
+ {stream, self}]),
+
+ receive
+ {http, {RequestId, stream_start, _Headers}} ->
+ ok;
+ {http, Msg} ->
+ tsf(Msg)
+ end,
+
+ StreamedBody = receive_streamed_body(RequestId, <<>>),
+
+ Body == binary_to_list(StreamedBody).
+
+
+%%-------------------------------------------------------------------------
+
+http_stream_once(doc) ->
+ ["Test the option stream for asynchrony requests"];
+http_stream_once(suite) ->
+ [];
+http_stream_once(Config) when is_list(Config) ->
+ p("http_stream_once -> entry with"
+ "~n Config: ~p", [Config]),
+
+ p("http_stream_once -> set ipfamily to inet", []),
+ ok = httpc:set_options([{ipfamily, inet}]),
+ p("http_stream_once -> start dummy server", []),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ PortStr = integer_to_list(Port),
+ p("http_stream_once -> once", []),
+ once(?URL_START ++ PortStr ++ "/once.html"),
+ p("http_stream_once -> once_chunked", []),
+ once(?URL_START ++ PortStr ++ "/once_chunked.html"),
+ p("http_stream_once -> dummy", []),
+ once(?URL_START ++ PortStr ++ "/dummy.html"),
+
+ p("http_stream_once -> stop dummy server", []),
+ DummyServerPid ! stop,
+ p("http_stream_once -> set ipfamily to inet6fb4", []),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ p("http_stream_once -> done", []),
+ ok.
+
+once(URL) ->
+ p("once -> issue sync request for ~p", [URL]),
+ {ok, {{_,200,_}, [_ | _], Body}} =
+ httpc:request(get, {URL, []}, [], []),
+
+ p("once -> issue async (self stream) request for ~p", [URL]),
+ {ok, RequestId} =
+ httpc:request(get, {URL, []}, [], [{sync, false},
+ {stream, {self, once}}]),
+
+ p("once -> await stream_start reply for (async) request ~p", [RequestId]),
+ NewPid =
+ receive
+ {http, {RequestId, stream_start, _Headers, Pid}} ->
+ p("once -> received stream_start reply for (async) request ~p: ~p",
+ [RequestId, Pid]),
+ Pid;
+ {http, Msg} ->
+ tsf(Msg)
+ end,
+
+ tsp("once -> request handler: ~p", [NewPid]),
+
+ p("once -> await stream reply for (async) request ~p", [RequestId]),
+ BodyPart =
+ receive
+ {http, {RequestId, stream, BinBodyPart}} ->
+ p("once -> received stream reply for (async) request ~p: "
+ "~n~p", [RequestId, binary_to_list(BinBodyPart)]),
+ BinBodyPart
+ end,
+
+ tsp("once -> first body part '~p' received", [binary_to_list(BodyPart)]),
+
+ StreamedBody = receive_streamed_body(RequestId, BinBodyPart, NewPid),
+
+ Body = binary_to_list(StreamedBody),
+
+ p("once -> done when Bode: ~p", [Body]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+parse_url(doc) ->
+ ["Test that an url is parsed correctly"];
+parse_url(suite) ->
+ [];
+parse_url(Config) when is_list(Config) ->
+ %% ipv6
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, true}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, false}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{foo, false}]),
+ {error,
+ {malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
+ http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
+
+ %% ipv4
+ {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
+ http_uri:parse("http://127.0.0.1/foobar.html"),
+
+ %% host
+ {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
+ http_uri:parse("http://localhost:8888/foobar.html"),
+
+ %% Userinfo
+ {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
+ http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
+
+ %% Scheme error
+ {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
+ {error, {malformed_url, _, _}} =
+ http_uri:parse("localhost:8888/foobar.html"),
+
+ %% Query
+ {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
+ http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
+
+ %% Esc chars
+ {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
+ http_uri:parse("http://www.somedomain.com/%2Eabc"),
+ {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
+ http_uri:parse("http://www.somedomain.com/%252Eabc"),
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
+ http_uri:parse("http://www.somedomain.com/%25abc"),
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
+ http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
+
+
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+ipv6_ipcomm() ->
+ [{require, ipv6_hosts}].
+ipv6_ipcomm(doc) ->
+ ["Test ip_comm ipv6."];
+ipv6_ipcomm(suite) ->
+ [];
+ipv6_ipcomm(Config) when is_list(Config) ->
+ HTTPOptions = [],
+ SocketType = ip_comm,
+ Scheme = "http",
+ Extra = [],
+ ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
+
+
+%%-------------------------------------------------------------------------
+
+ipv6_essl() ->
+ [{require, ipv6_hosts}].
+ipv6_essl(doc) ->
+ ["Test essl ipv6."];
+ipv6_essl(suite) ->
+ [];
+ipv6_essl(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+ SSLConfig = {essl, SSLOptions},
+ tsp("ssl_ipv6 -> make request using: "
+ "~n SSLOptions: ~p", [SSLOptions]),
+ HTTPOptions = [{ssl, SSLConfig}],
+ SocketType = essl,
+ Scheme = "https",
+ Extra = SSLOptions,
+ ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
+
+
+%%-------------------------------------------------------------------------
+
+ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
+ %% Check if we are a IPv6 host
+ tsp("ipv6 -> verify ipv6 support"),
+ case inets_test_lib:has_ipv6_support(Config) of
+ {ok, Addr} ->
+ tsp("ipv6 -> ipv6 supported: ~p", [Addr]),
+ {DummyServerPid, Port} = dummy_server(SocketType, ipv6, Extra),
+ Profile = ?config(profile, Config),
+ URL =
+ Scheme ++
+ "://[" ++ http_transport:ipv6_name(Addr) ++ "]:" ++
+ integer_to_list(Port) ++ "/foobar.html",
+ tsp("ipv6 -> issue request with: "
+ "~n URL: ~p"
+ "~n HTTPOptions: ~p", [URL, HTTPOptions]),
+ case httpc:request(get, {URL, []}, HTTPOptions, [], Profile) of
+ {ok, {{_,200,_}, [_ | _], [_|_]}} ->
+ tsp("ipv6 -> expected result"),
+ DummyServerPid ! stop,
+ ok;
+ {ok, Unexpected} ->
+ tsp("ipv6 -> unexpected result: "
+ "~n ~p", [Unexpected]),
+ DummyServerPid ! stop,
+ tsf({unexpected_result, Unexpected});
+ {error, Reason} ->
+ tsp("ipv6 -> error: "
+ "~n Reason: ~p", [Reason]),
+ DummyServerPid ! stop,
+ tsf(Reason)
+ end,
+ ok;
+ _ ->
+ tsp("ipv6 -> ipv6 not supported"),
+ skip("Host does not support IPv6")
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+headers_as_is(doc) ->
+ ["Test the option headers_as_is"];
+headers_as_is(suite) ->
+ [];
+headers_as_is(Config) when is_list(Config) ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, {{_,200,_}, [_|_], [_|_]}} =
+ httpc:request(get, {URL, [{"Host", "localhost"},{"Te", ""}]},
+ [], [{headers_as_is, true}]),
+
+ {ok, {{_,400,_}, [_|_], [_|_]}} =
+ httpc:request(get, {URL, [{"Te", ""}]},[], [{headers_as_is, true}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+selecting_session(doc) ->
+ ["Test selection of sessions - OTP-9847"];
+selecting_session(suite) ->
+ [];
+selecting_session(Config) when is_list(Config) ->
+ tsp("selecting_session -> entry with"
+ "~n Config: ~p", [Config]),
+
+ tsp("selecting_session -> set ipfamily to inet"),
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ tsp("selecting_session -> start server"),
+ {ServerPid, Port} = otp_9847_server(),
+
+ PortStr = integer_to_list(Port),
+ URL = ?URL_START ++ PortStr ++ "/index.html",
+
+ tsp("selecting_session -> issue the first batch (three) requests"),
+ lists:foreach(fun(P) ->
+ tsp("selecting_session:fun1 -> "
+ "send stop request to ~p", [P]),
+ P ! stop
+ end,
+ reqs(URL, ServerPid, 3, 3, false)),
+ tsp("selecting_session -> sleep some (1) to make sure nothing lingers"),
+ ?SLEEP(5000),
+ tsp("selecting_session -> "
+ "instruct the server to reply to the first request"),
+ ServerPid ! {answer, true},
+ receive
+ {answer, true} ->
+ tsp("selecting_session -> "
+ "received ack from server to reply to the first request"),
+ ok
+ end,
+ tsp("selecting_session -> issue the second batch (four) requests"),
+ lists:foreach(fun(P) ->
+ tsp("selecting_session:fun2 -> "
+ "send stop request to ~p", [P]),
+ P ! stop
+ end,
+ reqs(URL, ServerPid, 4, 1, true)),
+ tsp("selecting_session -> sleep some (2) to make sure nothing lingers"),
+ ?SLEEP(5000),
+
+ tsp("selecting_session -> stop server"),
+ ServerPid ! stop,
+ tsp("selecting_session -> set ipfamily (back) to inet6fb4"),
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ tsp("selecting_session -> done"),
+ ok.
+
+reqs(URL, ServerPid, NumReqs, NumHandlers, InitialSync) ->
+ tsp("reqs -> entry with"
+ "~n URL: ~p"
+ "~n ServerPid: ~w"
+ "~n NumReqs: ~w"
+ "~n NumHandlers: ~w"
+ "~n InitialSync: ~w",
+ [URL, ServerPid, NumReqs, NumHandlers, InitialSync]),
+ Handlers = reqs2(URL, NumReqs, [], InitialSync),
+ tsp("reqs -> "
+ "~n Handlers: ~w", [Handlers]),
+ case length(Handlers) of
+ NumHandlers ->
+ tsp("reqs -> "
+ "~n NumHandlers: ~w", [NumHandlers]),
+ ServerPid ! num_handlers,
+ receive
+ {num_handlers, NumHandlers} ->
+ tsp("reqs -> received num_handlers with"
+ "~n NumHandlers: ~w", [NumHandlers]),
+ Handlers;
+ {num_handlers, WrongNumHandlers} ->
+ tsp("reqs -> received num_handlers with"
+ "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
+ exit({wrong_num_handlers1, WrongNumHandlers, NumHandlers})
+ end;
+ WrongNumHandlers ->
+ tsp("reqs -> "
+ "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
+ exit({wrong_num_handlers2, WrongNumHandlers, NumHandlers})
+ end.
+
+
+reqs2(_URL, 0, Acc, _Sync) ->
+ lists:reverse(Acc);
+reqs2(URL, Num, Acc, Sync) ->
+ tsp("reqs2 -> entry with"
+ "~n Num: ~w"
+ "~n Sync: ~w", [Num, Sync]),
+ case httpc:request(get, {URL, []}, [], [{sync, Sync}]) of
+ {ok, _Reply} ->
+ tsp("reqs2 -> successful request: ~p", [_Reply]),
+ receive
+ {handler, Handler, _Manager} ->
+ %% This is when a new handler is created
+ tsp("reqs2 -> received handler: ~p", [Handler]),
+ case lists:member(Handler, Acc) of
+ true ->
+ tsp("reqs2 -> duplicate handler"),
+ exit({duplicate_handler, Handler, Num, Acc});
+ false ->
+ tsp("reqs2 -> wait for data ack"),
+ receive
+ {data_received, Handler} ->
+ tsp("reqs2 -> "
+ "received data ack from ~p", [Handler]),
+ case Sync of
+ true ->
+ reqs2(URL, Num-1, [Handler|Acc],
+ false);
+ false ->
+ reqs2(URL, Num-1, [Handler|Acc],
+ Sync)
+ end
+ end
+ end;
+
+ {data_received, Handler} ->
+ tsp("reqs2 -> "
+ "received data ack from ~p", [Handler]),
+ reqs2(URL, Num-1, Acc, false)
+
+ end;
+
+ {error, Reason} ->
+ tsp("reqs2 -> request ~w failed: ~p", [Num, Reason]),
+ exit({request_failed, Reason, Num, Acc})
+ end.
+
+otp_9847_server() ->
+ TC = self(),
+ Pid = spawn_link(fun() -> otp_9847_server_init(TC) end),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+otp_9847_server_init(TC) ->
+ tsp("otp_9847_server_init -> entry with"
+ "~n TC: ~p", [TC]),
+ {ok, ListenSocket} =
+ gen_tcp:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}]),
+ tsp("otp_9847_server_init -> listen socket created: "
+ "~n ListenSocket: ~p", [ListenSocket]),
+ {ok, Port} = inet:port(ListenSocket),
+ tsp("otp_9847_server_init -> Port: ~p", [Port]),
+ TC ! {port, Port},
+ otp_9847_server_main(TC, ListenSocket, false, []).
+
+otp_9847_server_main(TC, ListenSocket, Answer, Handlers) ->
+ tsp("otp_9847_server_main -> entry with"
+ "~n TC: ~p"
+ "~n ListenSocket: ~p"
+ "~n Answer: ~p"
+ "~n Handlers: ~p", [TC, ListenSocket, Answer, Handlers]),
+ case gen_tcp:accept(ListenSocket, 1000) of
+ {ok, Sock} ->
+ tsp("otp_9847_server_main -> accepted"
+ "~n Sock: ~p", [Sock]),
+ {Handler, Mon, Port} = otp_9847_handler(TC, Sock, Answer),
+ tsp("otp_9847_server_main -> handler ~p created for ~w",
+ [Handler, Port]),
+ gen_tcp:controlling_process(Sock, Handler),
+ tsp("otp_9847_server_main -> control transfer"),
+ Handler ! owner,
+ tsp("otp_9847_server_main -> "
+ "handler ~p informed of owner transfer", [Handler]),
+ TC ! {handler, Handler, self()},
+ tsp("otp_9847_server_main -> "
+ "TC ~p informed of handler ~p", [TC, Handler]),
+ otp_9847_server_main(TC, ListenSocket, Answer,
+ [{Handler, Mon, Sock, Port}|Handlers]);
+
+ {error, timeout} ->
+ tsp("otp_9847_server_main -> timeout"),
+ receive
+ {answer, true} ->
+ tsp("otp_9847_server_main -> received answer request"),
+ TC ! {answer, true},
+ otp_9847_server_main(TC, ListenSocket, true, Handlers);
+
+ {'DOWN', _Mon, process, Pid, _Reason} ->
+ %% Could be one of the handlers
+ tsp("otp_9847_server_main -> received DOWN for ~p", [Pid]),
+ otp_9847_server_main(TC, ListenSocket, Answer,
+ lists:keydelete(Pid, 1, Handlers));
+
+ num_handlers ->
+ tsp("otp_9847_server_main -> "
+ "received request for number of handlers (~w)",
+ [length(Handlers)]),
+ TC ! {num_handlers, length(Handlers)},
+ otp_9847_server_main(TC, ListenSocket, Answer, Handlers);
+
+ stop ->
+ tsp("otp_9847_server_main -> received stop request"),
+ %% Stop all handlers (just in case)
+ Pids = [Handler || {Handler, _, _} <- Handlers],
+ lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
+ exit(normal);
+
+ Any ->
+ tsp("otp_9847_server_main -> received"
+ "~n Any: ~p", [Any]),
+ exit({crap, Any})
+
+ after 0 ->
+ tsp("otp_9847_server_main -> nothing in queue"),
+ otp_9847_server_main(TC, ListenSocket, Answer, Handlers)
+ end;
+
+ Error ->
+ exit(Error)
+ end.
+
+
+otp_9847_handler(TC, Sock, Answer) ->
+ tsp("otp_9847_handler -> entry with"
+ "~n TC: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p", [TC, Sock, Answer]),
+ Self = self(),
+ {Pid, Mon} =
+ spawn_opt(fun() ->
+ otp_9847_handler_init(TC, Self, Sock, Answer)
+ end,
+ [monitor]),
+ receive
+ {port, Port} ->
+ tsp("otp_9847_handler -> received port message (from ~p)"
+ "~n Port: ~p", [Pid, Port]),
+ {Pid, Mon, Port}
+ end.
+
+
+otp_9847_handler_init(TC, Server, Sock, Answer) ->
+ tsp("otp_9847_handler_init -> entry with"
+ "~n TC: ~p"
+ "~n Server: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p", [TC, Server, Sock, Answer]),
+ {ok, Port} = inet:port(Sock),
+ Server ! {port, Port},
+ receive
+ owner ->
+ tsp("otp_9847_handler_init -> "
+ "received owner message - activate socket"),
+ inet:setopts(Sock, [{active, true}]),
+ otp_9847_handler_main(TC, Server, Sock, Answer, [?HTTP_MAX_HEADER_SIZE])
+ end.
+
+otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs) ->
+ tsp("otp_9847_handler_main -> entry with"
+ "~n TC: ~p"
+ "~n Server: ~p"
+ "~n Sock: ~p"
+ "~n Answer: ~p"
+ "~n ParseArgs: ~p", [TC, Server, Sock, Answer, ParseArgs]),
+ receive
+ stop ->
+ tsp("otp_9847_handler_main -> received stop request"),
+ exit(normal);
+
+ {tcp, Sock, _Data} when Answer =:= false ->
+ tsp("otp_9847_handler_main -> received tcp data - no answer"),
+ TC ! {data_received, self()},
+ inet:setopts(Sock, [{active, true}]),
+ %% Ignore all data
+ otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs);
+
+ {tcp, Sock, Data} when Answer =:= true ->
+ tsp("otp_9847_handler_main -> received tcp data - answer"),
+ TC ! {data_received, self()},
+ inet:setopts(Sock, [{active, true}]),
+ NewParseArgs = otp_9847_handler_request(Sock, [Data|ParseArgs]),
+ otp_9847_handler_main(TC, Server, Sock, Answer, NewParseArgs);
+
+ {tcp_closed, Sock} ->
+ tsp("otp_9847_handler_main -> received tcp socket closed"),
+ exit(normal);
+
+ {tcp_error, Sock, Reason} ->
+ tsp("otp_9847_handler_main -> socket error: ~p", [Reason]),
+ (catch gen_tcp:close(Sock)),
+ exit(normal)
+
+ %% after 30000 ->
+ %% gen_tcp:close(Sock),
+ %% exit(normal)
+ end.
+
+otp_9847_handler_request(Sock, Args) ->
+ Msg =
+ case httpd_request:parse(Args) of
+ {ok, {_, "/index.html" = _RelUrl, _, _, _}} ->
+ B =
+ "<HTML><BODY>" ++
+ "...some body part..." ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
+ end,
+ gen_tcp:send(Sock, Msg),
+ [?HTTP_MAX_HEADER_SIZE].
+
+
+
+%%-------------------------------------------------------------------------
+
+options(doc) ->
+ ["Test the option parameters."];
+options(suite) ->
+ [];
+options(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ {ok, {{_,200,_}, [_ | _], Bin}}
+ = httpc:request(get, {URL, []}, [{foo, bar}],
+ %% Ignore unknown options
+ [{body_format, binary}, {foo, bar}]),
+
+ true = is_binary(Bin),
+ {ok, {200, [_|_]}}
+ = httpc:request(get, {URL, []}, [{timeout, infinity}],
+ [{full_result, false}]);
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+http_invalid_http(doc) ->
+ ["Test parse error"];
+http_invalid_http(suite) ->
+ [];
+http_invalid_http(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/invalid_http.html",
+
+ {error, {could_not_parse_as_http, _} = Reason} =
+ httpc:request(get, {URL, []}, [], []),
+
+ test_server:format("Parse error: ~p ~n", [Reason]),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+-define(GOOGLE, "www.google.com").
+
+hexed_query_otp_6191(doc) ->
+ [];
+hexed_query_otp_6191(suite) ->
+ [];
+hexed_query_otp_6191(Config) when is_list(Config) ->
+ Google = ?GOOGLE,
+ GoogleSearch = "http://" ++ Google ++ "/search",
+ Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
+ URI1 = GoogleSearch ++ Search1,
+ Search2 = "?hl=en&q=%25%25",
+ URI2 = GoogleSearch ++ Search2,
+ Search3 = "?hl=en&q=%foo",
+ URI3 = GoogleSearch ++ Search3,
+
+ Verify1 =
+ fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
+ (_) -> error
+ end,
+ Verify2 = Verify1,
+ Verify3 = Verify1,
+ verify_uri(URI1, Verify1),
+ verify_uri(URI2, Verify2),
+ verify_uri(URI3, Verify3),
+ ok.
+
+verify_uri(URI, Verify) ->
+ case http_uri:parse(URI) of
+ {ok, ParsedURI} ->
+ case Verify(ParsedURI) of
+ ok ->
+ ok;
+ error ->
+ Reason = {unexpected_parse_result, URI, ParsedURI},
+ ERROR = {error, Reason},
+ throw(ERROR)
+ end;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+empty_body_otp_6243(doc) ->
+ ["An empty body was not returned directly. There was a delay for several"
+ "seconds."];
+empty_body_otp_6243(suite) ->
+ [];
+empty_body_otp_6243(Config) when is_list(Config) ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/empty.html",
+ {ok, {{_,200,_}, [_ | _], []}} =
+ httpc:request(get, {URL, []}, [{timeout, 500}], []).
+
+
+%%-------------------------------------------------------------------------
+
+transfer_encoding_otp_6807(doc) ->
+ ["Transfer encoding is case insensitive"];
+transfer_encoding_otp_6807(suite) ->
+ [];
+transfer_encoding_otp_6807(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++
+ "/capital_transfer_encoding.html",
+ {ok, {{_,200,_}, [_|_], [_ | _]}} = httpc:request(URL),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+empty_response_header_otp_6830(doc) ->
+ ["Test the case that the HTTP server does not send any headers"];
+empty_response_header_otp_6830(suite) ->
+ [];
+empty_response_header_otp_6830(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/no_headers.html",
+ {ok, {{_,200,_}, [], [_ | _]}} = httpc:request(URL),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+no_content_204_otp_6982(doc) ->
+ ["Test the case that the HTTP 204 no content header"];
+no_content_204_otp_6982(suite) ->
+ [];
+no_content_204_otp_6982(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/no_content.html",
+ {ok, {{_,204,_}, [], []}} = httpc:request(URL),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+missing_CR_otp_7304(doc) ->
+ ["Test the case that the HTTP server uses only LF instead of CRLF"
+ "as delimitor"];
+missing_CR_otp_7304(suite) ->
+ [];
+missing_CR_otp_7304(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_CR.html",
+ {ok, {{_,200,_}, _, [_ | _]}} = httpc:request(URL),
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+otp_7883_1(doc) ->
+ ["OTP-7883-sync"];
+otp_7883_1(suite) ->
+ [];
+otp_7883_1(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
+ {error, socket_closed_remotely} = httpc:request(URL),
+ DummyServerPid ! stop,
+
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+otp_7883_2(doc) ->
+ ["OTP-7883-async"];
+otp_7883_2(suite) ->
+ [];
+otp_7883_2(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
+ Method = get,
+ Request = {URL, []},
+ HttpOptions = [],
+ Options = [{sync, false}],
+ Profile = httpc:default_profile(),
+ {ok, RequestId} =
+ httpc:request(Method, Request, HttpOptions, Options, Profile),
+ ok =
+ receive
+ {http, {RequestId, {error, socket_closed_remotely}}} ->
+ ok
+ end,
+ DummyServerPid ! stop,
+
+ ok = httpc:set_options([{ipfamily, inet6fb4}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+otp_8154_1(doc) ->
+ ["OTP-8154"];
+otp_8154_1(suite) ->
+ [];
+otp_8154_1(Config) when is_list(Config) ->
+ start_inets(),
+ ReqSeqNumServer = start_sequence_number_server(),
+ RespSeqNumServer = start_sequence_number_server(),
+ {ok, Server, Port} = start_slow_server(RespSeqNumServer),
+ Clients = run_clients(105, Port, ReqSeqNumServer),
+ %% ok = wait_for_clients(Clients),
+ ok = wait4clients(Clients, timer:minutes(3)),
+ Server ! shutdown,
+ RespSeqNumServer ! shutdown,
+ ReqSeqNumServer ! shutdown,
+ ok.
+
+start_inets() ->
+ inets:start(),
+ ok.
+
+
+%% -----------------------------------------------------
+%% A sequence number handler
+%% The purpose is to be able to pair requests with responses.
+
+start_sequence_number_server() ->
+ proc_lib:spawn(fun() -> loop_sequence_number(1) end).
+
+loop_sequence_number(N) ->
+ receive
+ shutdown ->
+ ok;
+ {From, get_next} ->
+ From ! {next_is, N},
+ loop_sequence_number(N + 1)
+ end.
+
+get_next_sequence_number(SeqNumServer) ->
+ SeqNumServer ! {self(), get_next},
+ receive {next_is, N} -> N end.
+
+%% -----------------------------------------------------
+%% Client part
+%% Sends requests randomly parallel
+
+run_clients(NumClients, ServerPort, SeqNumServer) ->
+ io:format("start clients when"
+ "~n NumClients: ~w"
+ "~n ServerPort: ~w"
+ "~n SeqNumServer: ~w"
+ "~n", [NumClients, ServerPort, SeqNumServer]),
+ set_random_seed(),
+ lists:map(
+ fun(Id) ->
+ io:format("starting client ~w~n", [Id]),
+ Req = f("req~3..0w", [get_next_sequence_number(SeqNumServer)]),
+ Url = f(?URL_START ++ "~w/~s", [ServerPort, Req]),
+ Pid = proc_lib:spawn(
+ fun() ->
+ io:format("[~w] client started - "
+ "issue request~n", [Id]),
+ case httpc:request(Url) of
+ {ok, {{_,200,_}, _, Resp}} ->
+ io:format("[~w] 200 response: "
+ "~p~n", [Id, Resp]),
+ case lists:prefix(Req++"->", Resp) of
+ true -> exit(normal);
+ false -> exit({bad_resp,Req,Resp})
+ end;
+ {ok, {{_,EC,Reason},_,Resp}} ->
+ io:format("[~w] ~w response: "
+ "~s~n~s~n",
+ [Id, EC, Reason, Resp]),
+ exit({bad_resp,Req,Resp});
+ Crap ->
+ io:format("[~w] bad response: ~p",
+ [Id, Crap]),
+ exit({bad_resp, Req, Crap})
+ end
+ end),
+ MRef = erlang:monitor(process, Pid),
+ timer:sleep(10 + random:uniform(1334)),
+ {Id, Pid, MRef}
+
+ end,
+ lists:seq(1, NumClients)).
+
+%% wait_for_clients(Clients) ->
+%% lists:foreach(
+%% fun({Id, Pid, MRef}) ->
+%% io:format("waiting for client ~w termination~n", [Id]),
+%% receive
+%% {'DOWN', MRef, process, Pid, normal} ->
+%% io:format("waiting for clients: "
+%% "normal exit from ~w (~p)~n",
+%% [Id, Pid]),
+%% ok;
+%% {'DOWN', MRef, process, Pid, Reason} ->
+%% io:format("waiting for clients: "
+%% "unexpected exit from ~w (~p):"
+%% "~n Reason: ~p"
+%% "~n", [Id, Pid, Reason]),
+%% erlang:error(Reason)
+%% end
+%% end,
+%% Clients).
+
+
+wait4clients([], _Timeout) ->
+ ok;
+wait4clients(Clients, Timeout) when Timeout > 0 ->
+ io:format("wait4clients -> entry with"
+ "~n length(Clients): ~w"
+ "~n Timeout: ~w"
+ "~n", [length(Clients), Timeout]),
+ T = t(),
+ receive
+ {'DOWN', _MRef, process, Pid, normal} ->
+ case lists:keysearch(Pid, 2, Clients) of
+ {value, {Id, _, _}} ->
+ io:format("receive normal exit message "
+ "from client ~p (~p)", [Id, Pid]),
+ NewClients =
+ lists:keydelete(Id, 1, Clients),
+ wait4clients(NewClients,
+ Timeout - (t() - T));
+ false ->
+ io:format("receive normal exit message "
+ "from unknown process: ~p", [Pid]),
+ wait4clients(Clients, Timeout - (t() - T))
+ end;
+
+ {'DOWN', _MRef, process, Pid, Reason} ->
+ case lists:keysearch(Pid, 2, Clients) of
+ {value, {Id, _, _}} ->
+ io:format("receive bad exit message "
+ "from client ~p (~p):"
+ "~n ~p", [Id, Pid, Reason]),
+ erlang:error({bad_client_termination, Id, Reason});
+ false ->
+ io:format("receive normal exit message "
+ "from unknown process: ~p", [Pid]),
+ wait4clients(Clients, Timeout - (t() - T))
+ end
+
+ after Timeout ->
+ erlang:error({client_timeout, Clients})
+ end;
+wait4clients(Clients, _) ->
+ erlang:error({client_timeout, Clients}).
+
+
+%% Time in milli seconds
+t() ->
+ {A,B,C} = erlang:now(),
+ A*1000000000+B*1000+(C div 1000).
+
+
+%% -----------------------------------------------------
+%% Webserver part:
+%% Implements a web server that sends responses one character
+%% at a time, with random delays between the characters.
+
+start_slow_server(SeqNumServer) ->
+ io:format("start slow server when"
+ "~n SeqNumServer: ~w"
+ "~n", [SeqNumServer]),
+ proc_lib:start(
+ erlang, apply, [fun() -> init_slow_server(SeqNumServer) end, []]).
+
+init_slow_server(SeqNumServer) ->
+ io:format("[webserver ~w] init slow server"
+ "~n", [SeqNumServer]),
+ {ok, LSock} = gen_tcp:listen(0, [binary, {packet,0}, {active,true},
+ {backlog, 100}]),
+ io:format("[webserver ~w] LSock: ~p"
+ "~n", [SeqNumServer, LSock]),
+ {ok, {_IP, Port}} = inet:sockname(LSock),
+ io:format("[webserver ~w] Port: ~w"
+ "~n", [SeqNumServer, Port]),
+ proc_lib:init_ack({ok, self(), Port}),
+ loop_slow_server(LSock, SeqNumServer).
+
+loop_slow_server(LSock, SeqNumServer) ->
+ io:format("[webserver ~w] entry with"
+ "~n LSock: ~p"
+ "~n", [SeqNumServer, LSock]),
+ Master = self(),
+ Acceptor = proc_lib:spawn(
+ fun() -> client_handler(Master, LSock, SeqNumServer) end),
+ io:format("[webserver ~w] acceptor started"
+ "~n Acceptor: ~p"
+ "~n", [SeqNumServer, Acceptor]),
+ receive
+ {accepted, Acceptor} ->
+ io:format("[webserver ~w] accepted"
+ "~n", [SeqNumServer]),
+ loop_slow_server(LSock, SeqNumServer);
+ shutdown ->
+ gen_tcp:close(LSock),
+ exit(Acceptor, kill)
+ end.
+
+
+%% Handle one client connection
+client_handler(Master, LSock, SeqNumServer) ->
+ io:format("[acceptor ~w] await accept"
+ "~n", [SeqNumServer]),
+ {ok, CSock} = gen_tcp:accept(LSock),
+ io:format("[acceptor ~w] accepted"
+ "~n CSock: ~p"
+ "~n", [SeqNumServer, CSock]),
+ Master ! {accepted, self()},
+ set_random_seed(),
+ loop_client(1, CSock, SeqNumServer).
+
+loop_client(N, CSock, SeqNumServer) ->
+ %% Await request, don't bother parsing it too much,
+ %% assuming the entire request arrives in one packet.
+ io:format("[acceptor ~w] await request"
+ "~n N: ~p"
+ "~n", [SeqNumServer, N]),
+ receive
+ {tcp, CSock, Req} ->
+ ReqNum = parse_req_num(Req),
+ RespSeqNum = get_next_sequence_number(SeqNumServer),
+ Response = f("~s->resp~3..0w/~2..0w", [ReqNum, RespSeqNum, N]),
+ Txt = f("Slow server (~p) got ~p, answering with ~p",
+ [self(), Req, Response]),
+ io:format("~s...~n", [Txt]),
+ slowly_send_response(CSock, Response),
+ case parse_connection_type(Req) of
+ keep_alive ->
+ io:format("~s...done~n", [Txt]),
+ loop_client(N+1, CSock, SeqNumServer);
+ close ->
+ io:format("~s...done (closing)~n", [Txt]),
+ gen_tcp:close(CSock)
+ end
+ end.
+
+slowly_send_response(CSock, Answer) ->
+ Response = f("HTTP/1.1 200 OK\r\nContent-Length: ~w\r\n\r\n~s",
+ [length(Answer), Answer]),
+ lists:foreach(
+ fun(Char) ->
+ timer:sleep(random:uniform(500)),
+ gen_tcp:send(CSock, <<Char>>)
+ end,
+ Response).
+
+parse_req_num(Request) ->
+ Opts = [caseless,{capture,all_but_first,list}],
+ {match, [ReqNum]} = re:run(Request, "GET /(.*) HTTP", Opts),
+ ReqNum.
+
+parse_connection_type(Request) ->
+ Opts = [caseless,{capture,all_but_first,list}],
+ {match,[CType]} = re:run(Request, "connection: *(keep-alive|close)", Opts),
+ case string:to_lower(CType) of
+ "close" -> close;
+ "keep-alive" -> keep_alive
+ end.
+
+
+set_random_seed() ->
+ {_, _, Micros} = now(),
+ A = erlang:phash2([make_ref(), self(), Micros]),
+ random:seed(A, A, A).
+
+f(F, A) -> lists:flatten(io_lib:format(F,A)).
+
+
+
+
+%%-------------------------------------------------------------------------
+
+
+
+otp_8106_pid(doc) ->
+ ["OTP-8106 - deliver reply info using \"other\" pid"];
+otp_8106_pid(suite) ->
+ [];
+otp_8106_pid(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ ReceiverPid = create_receiver(pid),
+ Receiver = ReceiverPid,
+
+ otp8106(ReceiverPid, Receiver, Config),
+
+ stop_receiver(ReceiverPid),
+
+ ok;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+otp_8106_fun(doc) ->
+ ["OTP-8106 - deliver reply info using fun"];
+otp_8106_fun(suite) ->
+ [];
+otp_8106_fun(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ ReceiverPid = create_receiver(function),
+ Receiver = otp_8106_deliver_fun(ReceiverPid),
+
+ otp8106(ReceiverPid, Receiver, Config),
+
+ stop_receiver(ReceiverPid),
+
+ ok;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+otp_8106_mfa(doc) ->
+ ["OTP-8106 - deliver reply info using mfa callback"];
+otp_8106_mfa(suite) ->
+ [];
+otp_8106_mfa(Config) when is_list(Config) ->
+ case ?config(local_server, Config) of
+ ok ->
+ ReceiverPid = create_receiver(mfa),
+ Receiver = {?MODULE, otp_8106_deliver, [mfa, ReceiverPid]},
+
+ otp8106(ReceiverPid, Receiver, Config),
+
+ stop_receiver(ReceiverPid),
+
+ ok;
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+ otp8106(ReceiverPid, Receiver, Config) ->
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HTTPOptions = [],
+ Options = [{sync, false}, {receiver, Receiver}],
+
+ {ok, RequestId} =
+ httpc:request(get, Request, HTTPOptions, Options),
+
+ Body =
+ receive
+ {reply, ReceiverPid, {RequestId, {{_, 200, _}, _, B}}} ->
+ B;
+ {reply, ReceiverPid, Msg} ->
+ tsf(Msg);
+ {bad_reply, ReceiverPid, Msg} ->
+ tsf(Msg)
+ end,
+
+ inets_test_lib:check_body(binary_to_list(Body)),
+ ok.
+
+
+create_receiver(Type) ->
+ Parent = self(),
+ Receiver = fun() -> receiver(Type, Parent) end,
+ spawn_link(Receiver).
+
+stop_receiver(Pid) ->
+ Pid ! {stop, self()}.
+
+receiver(Type, Parent) ->
+ receive
+ {stop, Parent} ->
+ exit(normal);
+
+ {http, ReplyInfo} when (Type =:= pid) ->
+ Parent ! {reply, self(), ReplyInfo},
+ receiver(Type, Parent);
+
+ {Type, ReplyInfo} ->
+ Parent ! {reply, self(), ReplyInfo},
+ receiver(Type, Parent);
+
+ Crap ->
+ Parent ! {reply, self(), {bad_reply, Crap}},
+ receiver(Type, Parent)
+ end.
+
+
+otp_8106_deliver_fun(ReceiverPid) ->
+ fun(ReplyInfo) -> otp_8106_deliver(ReplyInfo, function, ReceiverPid) end.
+
+otp_8106_deliver(ReplyInfo, Type, ReceiverPid) ->
+ ReceiverPid ! {Type, ReplyInfo},
+ ok.
+
+
+
+%%-------------------------------------------------------------------------
+
+otp_8056(doc) ->
+ "OTP-8056";
+otp_8056(suite) ->
+ [];
+otp_8056(Config) when is_list(Config) ->
+ Method = get,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ HTTPOptions = [],
+ Options1 = [{sync, true}, {stream, {self, once}}],
+ Options2 = [{sync, true}, {stream, self}],
+ {error, streaming_error} = httpc:request(Method, Request,
+ HTTPOptions, Options1),
+ tsp("request 1 failed as expected"),
+ {error, streaming_error} = httpc:request(Method, Request,
+ HTTPOptions, Options2),
+ tsp("request 2 failed as expected"),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+otp_8352(doc) ->
+ "OTP-8352";
+otp_8352(suite) ->
+ [];
+otp_8352(Config) when is_list(Config) ->
+ tsp("otp_8352 -> entry with"
+ "~n Config: ~p", [Config]),
+ case ?config(local_server, Config) of
+ ok ->
+ tsp("local-server running"),
+
+ tsp("initial profile info(1): ~p", [httpc:info()]),
+
+ MaxSessions = 5,
+ MaxKeepAlive = 10,
+ KeepAliveTimeout = timer:minutes(2),
+ ConnOptions = [{max_sessions, MaxSessions},
+ {max_keep_alive_length, MaxKeepAlive},
+ {keep_alive_timeout, KeepAliveTimeout}],
+ httpc:set_options(ConnOptions),
+
+ Method = get,
+ Port = ?config(local_port, Config),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Request = {URL, []},
+ Timeout = timer:seconds(1),
+ ConnTimeout = Timeout + timer:seconds(1),
+ HttpOptions1 = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
+ Options1 = [{socket_opts, [{tos, 87},
+ {recbuf, 16#FFFF},
+ {sndbuf, 16#FFFF}]}],
+ case httpc:request(Method, Request, HttpOptions1, Options1) of
+ {ok, {{_,200,_}, [_ | _], ReplyBody1 = [_ | _]}} ->
+ %% equivaliant to httpc:request(get, {URL, []}, [], []),
+ inets_test_lib:check_body(ReplyBody1);
+ {ok, UnexpectedReply1} ->
+ tsf({unexpected_reply, UnexpectedReply1});
+ {error, _} = Error1 ->
+ tsf({bad_reply, Error1})
+ end,
+
+ tsp("profile info (2): ~p", [httpc:info()]),
+
+ HttpOptions2 = [],
+ Options2 = [{socket_opts, [{tos, 84},
+ {recbuf, 32#1FFFF},
+ {sndbuf, 32#1FFFF}]}],
+ case httpc:request(Method, Request, HttpOptions2, Options2) of
+ {ok, {{_,200,_}, [_ | _], ReplyBody2 = [_ | _]}} ->
+ %% equivaliant to httpc:request(get, {URL, []}, [], []),
+ inets_test_lib:check_body(ReplyBody2);
+ {ok, UnexpectedReply2} ->
+ tsf({unexpected_reply, UnexpectedReply2});
+ {error, _} = Error2 ->
+ tsf({bad_reply, Error2})
+ end,
+ tsp("profile info (3): ~p", [httpc:info()]),
+ ok;
+
+ _ ->
+ skip("Failed to start local http-server")
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+otp_8371(doc) ->
+ ["OTP-8371"];
+otp_8371(suite) ->
+ [];
+otp_8371(Config) when is_list(Config) ->
+ ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
+ {DummyServerPid, Port} = dummy_server(ipv4),
+
+ URL = ?URL_START ++ integer_to_list(Port) ++
+ "/ensure_host_header_with_port.html",
+
+ case httpc:request(get, {URL, []}, [], []) of
+ {ok, Result} ->
+ case Result of
+ {{_, 200, _}, _Headers, Body} ->
+ tsp("expected response with"
+ "~n Body: ~p", [Body]),
+ ok;
+ {StatusLine, Headers, Body} ->
+ tsp("expected response with"
+ "~n StatusLine: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p", [StatusLine, Headers, Body]),
+ tsf({unexpected_result,
+ [{status_line, StatusLine},
+ {headers, Headers},
+ {body, Body}]});
+ _ ->
+ tsf({unexpected_result, Result})
+ end;
+ Error ->
+ tsf({request_failed, Error})
+ end,
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipv6, enabled}]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+otp_8739(doc) ->
+ ["OTP-8739"];
+otp_8739(suite) ->
+ [];
+otp_8739(Config) when is_list(Config) ->
+ {_DummyServerPid, Port} = otp_8739_dummy_server(),
+ URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
+ Method = get,
+ Request = {URL, []},
+ HttpOptions = [{connect_timeout, 500}, {timeout, 1}],
+ Options = [{sync, true}],
+ case httpc:request(Method, Request, HttpOptions, Options) of
+ {error, timeout} ->
+ %% And now we check the size of the handler db
+ Info = httpc:info(),
+ tsp("Info: ~p", [Info]),
+ {value, {handlers, Handlers}} =
+ lists:keysearch(handlers, 1, Info),
+ case Handlers of
+ [] ->
+ ok;
+ _ ->
+ tsf({unexpected_handlers, Handlers})
+ end;
+ Unexpected ->
+ tsf({unexpected, Unexpected})
+ end.
+
+
+otp_8739_dummy_server() ->
+ Parent = self(),
+ Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+otp_8739_dummy_server_init(Parent) ->
+ {ok, ListenSocket} =
+ gen_tcp:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}]),
+ {ok, Port} = inet:port(ListenSocket),
+ Parent ! {port, Port},
+ otp_8739_dummy_server_main(Parent, ListenSocket).
+
+otp_8739_dummy_server_main(_Parent, ListenSocket) ->
+ case gen_tcp:accept(ListenSocket) of
+ {ok, Sock} ->
+ %% Ignore the request, and simply wait for the socket to close
+ receive
+ {tcp_closed, Sock} ->
+ (catch gen_tcp:close(ListenSocket)),
+ exit(normal);
+ {tcp_error, Sock, Reason} ->
+ tsp("socket error: ~p", [Reason]),
+ (catch gen_tcp:close(ListenSocket)),
+ exit(normal)
+ after 10000 ->
+ %% Just in case
+ (catch gen_tcp:close(Sock)),
+ (catch gen_tcp:close(ListenSocket)),
+ exit(timeout)
+ end;
+ Error ->
+ exit(Error)
+ end.
+
+
+%%-------------------------------------------------------------------------
+
+initial_server_connect(doc) ->
+ ["If this test cases times out the init of httpc_handler process is"
+ "blocking the manager/client process (implementation dependent which) but nither"
+ "should be blocked."];
+initial_server_connect(suite) ->
+ [];
+initial_server_connect(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ok = httpc:set_options([{ipfamily, inet}]),
+
+ CertFile = filename:join(DataDir, "ssl_server_cert.pem"),
+ SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
+
+ {DummyServerPid, Port} = dummy_ssl_server_hang(self(), ipv4, SSLOptions),
+
+ URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/index.html",
+
+ httpc:request(get, {URL, []}, [{ssl,{essl,[]}}], [{sync, false}]),
+
+ [{session_cookies,[]}] = httpc:which_cookies(),
+
+ DummyServerPid ! stop,
+ ok = httpc:set_options([{ipfamily, inet6fb4}]).
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
+ ConfDir = filename:join(ServerRoot, "conf"),
+ CgiDir = filename:join(ServerRoot, "cgi-bin"),
+ ok = file:make_dir(ServerRoot),
+ ok = file:make_dir(DocRoot),
+ ok = file:make_dir(ConfDir),
+ ok = file:make_dir(CgiDir),
+
+ {ok, Files} = file:list_dir(DataDir),
+
+ lists:foreach(fun(File) -> case lists:suffix(".html", File) of
+ true ->
+ inets_test_lib:copy_file(File,
+ DataDir,
+ DocRoot);
+ false ->
+ ok
+ end
+ end, Files),
+
+ Cgi = case test_server:os_type() of
+ {win32, _} ->
+ "cgi_echo.exe";
+ _ ->
+ "cgi_echo"
+ end,
+
+ inets_test_lib:copy_file(Cgi, DataDir, CgiDir),
+ inets_test_lib:copy_file("mime.types", DataDir, ConfDir).
+
+create_config(FileName, ComType, Port, PrivDir, ServerRoot, DocRoot,
+ SSLDir) ->
+ MaxHdrSz = io_lib:format("~p", [256]),
+ MaxHdrAct = io_lib:format("~p", [close]),
+ SSL =
+ case ComType of
+ ssl ->
+ [cline(["SSLCertificateFile ",
+ filename:join(SSLDir, "ssl_server_cert.pem")]),
+ cline(["SSLCertificateKeyFile ",
+ filename:join(SSLDir, "ssl_server_cert.pem")]),
+ cline(["SSLVerifyClient 0"])];
+ _ ->
+ []
+ end,
+
+ Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
+ " mod_include mod_dir mod_get mod_head"
+ " mod_log mod_disk_log mod_trace",
+
+ %% BindAddress = "*|inet", % Force the use of IPv4
+ BindAddress = "*", % This corresponds to using IpFamily inet6fb4
+
+ HttpConfig = [
+ cline(["BindAddress ", BindAddress]),
+ cline(["Port ", integer_to_list(Port)]),
+ cline(["ServerName ", "httpc_test"]),
+ cline(["SocketType ", atom_to_list(ComType)]),
+ cline([Mod_order]),
+ cline(["ServerRoot ", ServerRoot]),
+ cline(["DocumentRoot ", DocRoot]),
+ cline(["MaxHeaderSize ",MaxHdrSz]),
+ cline(["MaxHeaderAction ",MaxHdrAct]),
+ cline(["DirectoryIndex ", "index.html "]),
+ cline(["DefaultType ", "text/plain"]),
+ cline(["ScriptAlias /cgi-bin/ ",
+ filename:join(ServerRoot, "cgi-bin"), "/"]),
+ SSL],
+ ConfigFile = filename:join([PrivDir,FileName]),
+ {ok, Fd} = file:open(ConfigFile, [write]),
+ ok = file:write(Fd, lists:flatten(HttpConfig)),
+ ok = file:close(Fd).
+
+cline(List) ->
+ lists:flatten([List, "\r\n"]).
+
+receive_streamed_body(RequestId, Body) ->
+ receive
+ {http, {RequestId, stream, BinBodyPart}} ->
+ receive_streamed_body(RequestId,
+ <<Body/binary, BinBodyPart/binary>>);
+ {http, {RequestId, stream_end, _Headers}} ->
+ Body;
+ {http, Msg} ->
+ tsf(Msg)
+ end.
+
+receive_streamed_body(RequestId, Body, Pid) ->
+ httpc:stream_next(Pid),
+ test_server:format("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
+ receive
+ {http, {RequestId, stream, BinBodyPart}} ->
+ receive_streamed_body(RequestId,
+ <<Body/binary, BinBodyPart/binary>>,
+ Pid);
+ {http, {RequestId, stream_end, _Headers}} ->
+ Body;
+ {http, Msg} ->
+ tsf(Msg)
+ end.
+
+%% Perform a synchronous stop
+dummy_server_stop(Pid) ->
+ Pid ! {stop, self()},
+ receive
+ {stopped, Pid} ->
+ ok
+ end.
+
+dummy_server(IpV) ->
+ dummy_server(self(), ip_comm, IpV, []).
+
+dummy_server(SocketType, IpV, Extra) ->
+ dummy_server(self(), SocketType, IpV, Extra).
+
+dummy_server(Caller, SocketType, IpV, Extra) ->
+ Args = [Caller, SocketType, IpV, Extra],
+ Pid = spawn(httpc_SUITE, dummy_server_init, Args),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+dummy_server_init(Caller, ip_comm, IpV, _) ->
+ BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}],
+ {ok, ListenSocket} =
+ case IpV of
+ ipv4 ->
+ tsp("ip_comm ipv4 listen", []),
+ gen_tcp:listen(0, [inet | BaseOpts]);
+ ipv6 ->
+ tsp("ip_comm ipv6 listen", []),
+ gen_tcp:listen(0, [inet6 | BaseOpts])
+ end,
+ {ok, Port} = inet:port(ListenSocket),
+ tsp("dummy_server_init(ip_comm) -> Port: ~p", [Port]),
+ Caller ! {port, Port},
+ dummy_ipcomm_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
+ [], ListenSocket);
+dummy_server_init(Caller, essl, IpV, SSLOptions) ->
+ BaseOpts = [{ssl_imp, new},
+ {backlog, 128}, binary, {reuseaddr,true}, {active, false} |
+ SSLOptions],
+ dummy_ssl_server_init(Caller, BaseOpts, IpV).
+
+dummy_ssl_server_init(Caller, BaseOpts, IpV) ->
+ {ok, ListenSocket} =
+ case IpV of
+ ipv4 ->
+ tsp("dummy_ssl_server_init -> ssl ipv4 listen", []),
+ ssl:listen(0, [inet | BaseOpts]);
+ ipv6 ->
+ tsp("dummy_ssl_server_init -> ssl ipv6 listen", []),
+ ssl:listen(0, [inet6 | BaseOpts])
+ end,
+ tsp("dummy_ssl_server_init -> ListenSocket: ~p", [ListenSocket]),
+ {ok, {_, Port}} = ssl:sockname(ListenSocket),
+ tsp("dummy_ssl_server_init -> Port: ~p", [Port]),
+ Caller ! {port, Port},
+ dummy_ssl_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
+ [], ListenSocket).
+
+dummy_ipcomm_server_loop(MFA, Handlers, ListenSocket) ->
+ receive
+ stop ->
+ tsp("dummy_ipcomm_server_loop -> stop handlers", []),
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ tsp("dummy_ipcomm_server_loop -> "
+ "stop command from ~p for handlers (~p)", [From, Handlers]),
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ tsp("dummy_ipcomm_server_loop -> await accept", []),
+ {ok, Socket} = gen_tcp:accept(ListenSocket),
+ tsp("dummy_ipcomm_server_loop -> accepted: ~p", [Socket]),
+ HandlerPid = dummy_request_handler(MFA, Socket),
+ tsp("dummy_icomm_server_loop -> handler created: ~p", [HandlerPid]),
+ gen_tcp:controlling_process(Socket, HandlerPid),
+ tsp("dummy_ipcomm_server_loop -> "
+ "control transfered to handler", []),
+ HandlerPid ! ipcomm_controller,
+ tsp("dummy_ipcomm_server_loop -> "
+ "handler informed about control transfer", []),
+ dummy_ipcomm_server_loop(MFA, [HandlerPid | Handlers],
+ ListenSocket)
+ end.
+
+dummy_ssl_server_loop(MFA, Handlers, ListenSocket) ->
+ receive
+ stop ->
+ tsp("dummy_ssl_server_loop -> stop handlers", []),
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ tsp("dummy_ssl_server_loop -> "
+ "stop command from ~p for handlers (~p)", [From, Handlers]),
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ tsp("dummy_ssl_server_loop -> await accept", []),
+ {ok, Socket} = ssl:transport_accept(ListenSocket),
+ tsp("dummy_ssl_server_loop -> accepted: ~p", [Socket]),
+ HandlerPid = dummy_request_handler(MFA, Socket),
+ tsp("dummy_ssl_server_loop -> handler created: ~p", [HandlerPid]),
+ ssl:controlling_process(Socket, HandlerPid),
+ tsp("dummy_ssl_server_loop -> control transfered to handler", []),
+ HandlerPid ! ssl_controller,
+ tsp("dummy_ssl_server_loop -> "
+ "handler informed about control transfer", []),
+ dummy_ssl_server_loop(MFA, [HandlerPid | Handlers],
+ ListenSocket)
+ end.
+
+dummy_request_handler(MFA, Socket) ->
+ tsp("spawn request handler", []),
+ spawn(httpc_SUITE, dummy_request_handler_init, [MFA, Socket]).
+
+dummy_request_handler_init(MFA, Socket) ->
+ SockType =
+ receive
+ ipcomm_controller ->
+ tsp("dummy_request_handler_init -> "
+ "received ip_comm controller - activate", []),
+ inet:setopts(Socket, [{active, true}]),
+ ip_comm;
+ ssl_controller ->
+ tsp("dummy_request_handler_init -> "
+ "received ssl controller - activate", []),
+ ssl:setopts(Socket, [{active, true}]),
+ ssl
+ end,
+ dummy_request_handler_loop(MFA, SockType, Socket).
+
+dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
+ tsp("dummy_request_handler_loop -> entry with"
+ "~n Module: ~p"
+ "~n Function: ~p"
+ "~n Args: ~p", [Module, Function, Args]),
+ receive
+ {Proto, _, Data} when (Proto =:= tcp) orelse (Proto =:= ssl) ->
+ tsp("dummy_request_handler_loop -> [~w] Data ~p", [Proto, Data]),
+ case handle_request(Module, Function, [Data | Args], Socket, Proto) of
+ stop when Proto =:= tcp ->
+ gen_tcp:close(Socket);
+ stop when Proto =:= ssl ->
+ ssl:close(Socket);
+ NewMFA ->
+ dummy_request_handler_loop(NewMFA, SockType, Socket)
+ end;
+ stop when SockType =:= ip_comm ->
+ gen_tcp:close(Socket);
+ stop when SockType =:= ssl ->
+ ssl:close(Socket)
+ end.
+
+
+mk_close(tcp) -> fun(Sock) -> gen_tcp:close(Sock) end;
+mk_close(ssl) -> fun(Sock) -> ssl:close(Sock) end.
+
+mk_send(tcp) -> fun(Sock, Data) -> gen_tcp:send(Sock, Data) end;
+mk_send(ssl) -> fun(Sock, Data) -> ssl:send(Sock, Data) end.
+
+handle_request(Module, Function, Args, Socket, Proto) ->
+ Close = mk_close(Proto),
+ Send = mk_send(Proto),
+ handle_request(Module, Function, Args, Socket, Close, Send).
+
+handle_request(Module, Function, Args, Socket, Close, Send) ->
+ tsp("handle_request -> entry with"
+ "~n Module: ~p"
+ "~n Function: ~p"
+ "~n Args: ~p", [Module, Function, Args]),
+ case Module:Function(Args) of
+ {ok, Result} ->
+ tsp("handle_request -> ok"
+ "~n Result: ~p", [Result]),
+ case (catch handle_http_msg(Result, Socket, Close, Send)) of
+ stop ->
+ stop;
+ <<>> ->
+ tsp("handle_request -> empty data"),
+ {httpd_request, parse, [[<<>>, ?HTTP_MAX_HEADER_SIZE]]};
+ Data ->
+ handle_request(httpd_request, parse,
+ [Data |[?HTTP_MAX_HEADER_SIZE]], Socket,
+ Close, Send)
+ end;
+ NewMFA ->
+ tsp("handle_request -> "
+ "~n NewMFA: ~p", [NewMFA]),
+ NewMFA
+ end.
+
+handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket, Close, Send) ->
+ tsp("handle_http_msg -> entry with: "
+ "~n RelUri: ~p"
+ "~n Headers: ~p"
+ "~n Body: ~p", [RelUri, Headers, Body]),
+ NextRequest =
+ case RelUri of
+ "/dummy_headers.html" ->
+ <<>>;
+ "/no_headers.html" ->
+ stop;
+ "/just_close.html" ->
+ stop;
+ _ ->
+ ContentLength = content_length(Headers),
+ case size(Body) - ContentLength of
+ 0 ->
+ <<>>;
+ _ ->
+ <<_BodyThisReq:ContentLength/binary,
+ Next/binary>> = Body,
+ Next
+ end
+ end,
+
+ tsp("handle_http_msg -> NextRequest: ~p", [NextRequest]),
+ case (catch ets:lookup(cookie, cookies)) of
+ [{cookies, true}]->
+ tsp("handle_http_msg -> check cookies ~p", []),
+ check_cookie(Headers);
+ _ ->
+ ok
+ end,
+
+ DefaultResponse = "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:32\r\n\r\n"
+ "<HTML><BODY>foobar</BODY></HTML>",
+
+ Msg =
+ case RelUri of
+ "/just_close.html" ->
+ close;
+ "/no_content.html" ->
+ "HTTP/1.0 204 No Content\r\n\r\n";
+ "/no_headers.html" ->
+ "HTTP/1.0 200 OK\r\n\r\nTEST";
+ "/ensure_host_header_with_port.html" ->
+ %% tsp("handle_http_msg -> validate host with port"),
+ case ensure_host_header_with_port(Headers) of
+ true ->
+ B =
+ "<HTML><BODY>" ++
+ "host with port" ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B;
+ false ->
+ B =
+ "<HTML><BODY>" ++
+ "Internal Server Error - host without port" ++
+ "</BODY></HTML>",
+ Len = integer_to_list(length(B)),
+ "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
+ end;
+ "/300.html" ->
+ NewUri = ?URL_START ++
+ integer_to_list(?IP_PORT) ++ "/dummy.html",
+ "HTTP/1.1 300 Multiple Choices\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+ "/301.html" ->
+ NewUri = ?URL_START ++
+ integer_to_list(?IP_PORT) ++ "/dummy.html",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:80\r\n\r\n" ++
+ "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>";
+ "/302.html" ->
+ NewUri = ?URL_START ++
+ integer_to_list(?IP_PORT) ++ "/dummy.html",
+ "HTTP/1.1 302 Found \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:80\r\n\r\n" ++
+ "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>";
+ "/303.html" ->
+ NewUri = ?URL_START ++
+ integer_to_list(?IP_PORT) ++ "/dummy.html",
+ "HTTP/1.1 303 See Other \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:80\r\n\r\n" ++
+ "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>";
+ "/307.html" ->
+ NewUri = ?URL_START ++
+ integer_to_list(?IP_PORT) ++ "/dummy.html",
+ "HTTP/1.1 307 Temporary Rediect \r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:80\r\n\r\n" ++
+ "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>";
+ "/500.html" ->
+ "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:47\r\n\r\n" ++
+ "<HTML><BODY>Internal Server Error</BODY></HTML>";
+ "/503.html" ->
+ case ets:lookup(unavailable, 503) of
+ [{503, unavailable}] ->
+ ets:insert(unavailable, {503, available}),
+ "HTTP/1.1 503 Service Unavailable\r\n" ++
+ "Retry-After:5\r\n" ++
+ "Content-Length:47\r\n\r\n" ++
+ "<HTML><BODY>Internal Server Error</BODY></HTML>";
+ [{503, available}] ->
+ DefaultResponse;
+ [{503, long_unavailable}] ->
+ "HTTP/1.1 503 Service Unavailable\r\n" ++
+ "Retry-After:120\r\n" ++
+ "Content-Length:47\r\n\r\n" ++
+ "<HTML><BODY>Internal Server Error</BODY></HTML>"
+ end;
+ "/redirectloop.html" -> %% Create a potential endless loop!
+ {ok, Port} = inet:port(Socket),
+ NewUri = ?URL_START ++
+ integer_to_list(Port) ++ "/redirectloop.html",
+ "HTTP/1.1 300 Multiple Choices\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+ "/userinfo.html" ->
+ Challange = "HTTP/1.1 401 Unauthorized \r\n" ++
+ "WWW-Authenticate:Basic" ++"\r\n" ++
+ "Content-Length:0\r\n\r\n",
+ case auth_header(Headers) of
+ {ok, Value} ->
+ handle_auth(Value, Challange, DefaultResponse);
+ _ ->
+ Challange
+ end;
+ "/dummy_headers.html" ->
+ %% The client will only care about the Transfer-Encoding
+ %% header the rest of these headers are left to the
+ %% user to evaluate. This is not a valid response
+ %% it only tests that the header handling code works.
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:32\r\n" ++
+ "Pragma:1#no-cache\r\n" ++
+ "Via:1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" ++
+ "Warning:1#pseudonym foobar\r\n" ++
+ "Vary:*\r\n" ++
+ "Trailer:Other:inets_test\r\n" ++
+ "Upgrade:HTTP/2.0\r\n" ++
+ "Age:4711\r\n" ++
+ "Transfer-Encoding:chunked\r\n" ++
+ "Content-Encoding:foo\r\n" ++
+ "Content-Language:en\r\n" ++
+ "Content-Location:http://www.foobar.se\r\n" ++
+ "Content-MD5:104528739076276072743283077410617235478\r\n"
+ ++
+ "Content-Range:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
+ "Expires:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
+ "Proxy-Authenticate:#1Basic" ++
+ "\r\n\r\n",
+ Send(Socket, Head),
+ Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+ "/capital_transfer_encoding.html" ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ Send(Socket, Head),
+ Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+ "/cookie.html" ->
+ "HTTP/1.1 200 ok\r\n" ++
+ "set-cookie:" ++ "test_cookie=true; path=/;" ++
+ "max-age=60000\r\n" ++
+ "Content-Length:32\r\n\r\n"++
+ "<HTML><BODY>foobar</BODY></HTML>";
+ "/missing_crlf.html" ->
+ "HTTP/1.1 200 ok" ++
+ "Content-Length:32\r\n" ++
+ "<HTML><BODY>foobar</BODY></HTML>";
+ "/wrong_statusline.html" ->
+ "ok 200 HTTP/1.1\r\n\r\n" ++
+ "Content-Length:32\r\n\r\n" ++
+ "<HTML><BODY>foobar</BODY></HTML>";
+ "/once_chunked.html" ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:Chunked\r\n\r\n",
+ Send(Socket, Head),
+ Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
+ Send(Socket,
+ http_chunk:encode("obar</BODY></HTML>")),
+ http_chunk:encode_last();
+ "/once.html" ->
+ Head = "HTTP/1.1 200 ok\r\n" ++
+ "Content-Length:32\r\n\r\n",
+ Send(Socket, Head),
+ Send(Socket, "<HTML><BODY>fo"),
+ test_server:sleep(1000),
+ Send(Socket, "ob"),
+ test_server:sleep(1000),
+ Send(Socket, "ar</BODY></HTML>");
+ "/invalid_http.html" ->
+ "HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
+ "Transfer-Encoding:chunked\r\n\r\n";
+ "/missing_reason_phrase.html" ->
+ "HTTP/1.1 200\r\n" ++
+ "Content-Length: 32\r\n\r\n"
+ "<HTML><BODY>foobar</BODY></HTML>";
+ "/missing_CR.html" ->
+ "HTTP/1.1 200 ok\n" ++
+ "Content-Length:32\r\n\n"
+ "<HTML><BODY>foobar</BODY></HTML>";
+ _ ->
+ DefaultResponse
+ end,
+
+ tsp("handle_http_msg -> Msg: ~p", [Msg]),
+ case Msg of
+ ok ->
+ %% Previously, this resulted in an {error, einval}. Now what?
+ ok;
+ close ->
+ %% Nothing to send, just close
+ Close(Socket);
+ _ when is_list(Msg) orelse is_binary(Msg) ->
+ Send(Socket, Msg)
+ end,
+ tsp("handle_http_msg -> done"),
+ NextRequest.
+
+ensure_host_header_with_port([]) ->
+ false;
+ensure_host_header_with_port(["host: " ++ Host| _]) ->
+ case string:tokens(Host, [$:]) of
+ [ActualHost, Port] ->
+ tsp("ensure_host_header_with_port -> "
+ "~n ActualHost: ~p"
+ "~n Port: ~p", [ActualHost, Port]),
+ true;
+ _ ->
+ false
+ end;
+ensure_host_header_with_port([_|T]) ->
+ ensure_host_header_with_port(T).
+
+auth_header([]) ->
+ auth_header_not_found;
+auth_header(["authorization:" ++ Value | _]) ->
+ {ok, string:strip(Value)};
+auth_header([_ | Tail]) ->
+ auth_header(Tail).
+
+handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
+ case string:tokens(base64:decode_to_string(UserInfo), ":") of
+ ["alladin", "sesame"] = Auth ->
+ test_server:format("Auth: ~p~n", [Auth]),
+ DefaultResponse;
+ Other ->
+ test_server:format("UnAuth: ~p~n", [Other]),
+ Challange
+ end.
+
+check_cookie([]) ->
+ tsf(no_cookie_header);
+check_cookie(["cookie:" ++ _Value | _]) ->
+ ok;
+check_cookie([_Head | Tail]) ->
+ check_cookie(Tail).
+
+content_length([]) ->
+ 0;
+content_length(["content-length:" ++ Value | _]) ->
+ list_to_integer(string:strip(Value));
+content_length([_Head | Tail]) ->
+ content_length(Tail).
+
+%% -------------------------------------------------------------------------
+
+simple_request_and_verify(Config,
+ Method, Request, HttpOpts, Opts, VerifyResult)
+ when (is_list(Config) andalso
+ is_atom(Method) andalso
+ is_list(HttpOpts) andalso
+ is_list(Opts) andalso
+ is_function(VerifyResult, 1)) ->
+ tsp("request_and_verify -> entry with"
+ "~n Method: ~p"
+ "~n Request: ~p"
+ "~n HttpOpts: ~p"
+ "~n Opts: ~p", [Method, Request, HttpOpts, Opts]),
+ case ?config(local_server, Config) of
+ ok ->
+ tsp("request_and_verify -> local-server running"),
+ Result = (catch httpc:request(Method, Request, HttpOpts, Opts)),
+ VerifyResult(Result);
+ _ ->
+ tsp("request_and_verify -> local-server *not* running - skip"),
+ hard_skip("Local http-server not running")
+ end.
+
+
+
+
+not_implemented_yet() ->
+ exit(not_implemented_yet).
+
+p(F) ->
+ p(F, []).
+
+p(F, A) ->
+ io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
+
+tsp(F) ->
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
+tsp(F, A) ->
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
+
+tsf(Reason) ->
+ test_server:fail(Reason).
+
+
+dummy_ssl_server_hang(Caller, IpV, SslOpt) ->
+ Pid = spawn(httpc_SUITE, dummy_ssl_server_hang_init, [Caller, IpV, SslOpt]),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+dummy_ssl_server_hang_init(Caller, IpV, SslOpt) ->
+ {ok, ListenSocket} =
+ case IpV of
+ ipv4 ->
+ ssl:listen(0, [binary, inet, {packet, 0},
+ {reuseaddr,true},
+ {active, false}] ++ SslOpt);
+ ipv6 ->
+ ssl:listen(0, [binary, inet6, {packet, 0},
+ {reuseaddr,true},
+ {active, false}] ++ SslOpt)
+ end,
+ {ok, {_,Port}} = ssl:sockname(ListenSocket),
+ tsp("dummy_ssl_server_hang_init -> Port: ~p", [Port]),
+ Caller ! {port, Port},
+ {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
+ dummy_ssl_server_hang_loop(AcceptSocket).
+
+dummy_ssl_server_hang_loop(_) ->
+ %% Do not do ssl:ssl_accept as we
+ %% want to time out the underlying gen_tcp:connect
+ receive
+ stop ->
+ ok
+ end.
+
+hard_skip(Reason) ->
+ throw(skip(Reason)).
+
+skip(Reason) ->
+ {skip, Reason}.
diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl
new file mode 100644
index 0000000000..b2ad593629
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE.erl
@@ -0,0 +1,2444 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(old_httpd_SUITE).
+
+-include_lib("test_server/include/test_server.hrl").
+-include("test_server_line.hrl").
+-include("inets_test_lib.hrl").
+
+-include_lib("kernel/include/file.hrl").
+
+%% Test server specific exports
+-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]).
+-export([init_per_testcase/2, end_per_testcase/2,
+ init_per_suite/1, end_per_suite/1]).
+
+%% Core Server tests
+-export([
+ ip_mod_alias/1,
+ ip_mod_actions/1,
+ ip_mod_security/1,
+ ip_mod_auth/1,
+ ip_mod_auth_api/1,
+ ip_mod_auth_mnesia_api/1,
+ ip_mod_htaccess/1,
+ ip_mod_cgi/1,
+ ip_mod_esi/1,
+ ip_mod_get/1,
+ ip_mod_head/1,
+ ip_mod_all/1,
+ ip_load_light/1,
+ ip_load_medium/1,
+ ip_load_heavy/1,
+ ip_dos_hostname/1,
+ ip_time_test/1,
+ ip_block_disturbing_idle/1,
+ ip_block_non_disturbing_idle/1,
+ ip_block_503/1,
+ ip_block_disturbing_active/1,
+ ip_block_non_disturbing_active/1,
+ ip_block_disturbing_active_timeout_not_released/1,
+ ip_block_disturbing_active_timeout_released/1,
+ ip_block_non_disturbing_active_timeout_not_released/1,
+ ip_block_non_disturbing_active_timeout_released/1,
+ ip_block_disturbing_blocker_dies/1,
+ ip_block_non_disturbing_blocker_dies/1,
+ ip_restart_no_block/1,
+ ip_restart_disturbing_block/1,
+ ip_restart_non_disturbing_block/1
+ ]).
+
+-export([
+ essl_mod_alias/1,
+ essl_mod_actions/1,
+ essl_mod_security/1,
+ essl_mod_auth/1,
+ essl_mod_auth_api/1,
+ essl_mod_auth_mnesia_api/1,
+ essl_mod_htaccess/1,
+ essl_mod_cgi/1,
+ essl_mod_esi/1,
+ essl_mod_get/1,
+ essl_mod_head/1,
+ essl_mod_all/1,
+ essl_load_light/1,
+ essl_load_medium/1,
+ essl_load_heavy/1,
+ essl_dos_hostname/1,
+ essl_time_test/1,
+ essl_restart_no_block/1,
+ essl_restart_disturbing_block/1,
+ essl_restart_non_disturbing_block/1,
+ essl_block_disturbing_idle/1,
+ essl_block_non_disturbing_idle/1,
+ essl_block_503/1,
+ essl_block_disturbing_active/1,
+ essl_block_non_disturbing_active/1,
+ essl_block_disturbing_active_timeout_not_released/1,
+ essl_block_disturbing_active_timeout_released/1,
+ essl_block_non_disturbing_active_timeout_not_released/1,
+ essl_block_non_disturbing_active_timeout_released/1,
+ essl_block_disturbing_blocker_dies/1,
+ essl_block_non_disturbing_blocker_dies/1
+ ]).
+
+%%% HTTP 1.1 tests
+-export([ip_host/1, ip_chunked/1, ip_expect/1, ip_range/1,
+ ip_if_test/1, ip_http_trace/1, ip_http1_1_head/1,
+ ip_mod_cgi_chunked_encoding_test/1]).
+
+%%% HTTP 1.0 tests
+-export([ip_head_1_0/1, ip_get_1_0/1, ip_post_1_0/1]).
+
+%%% HTTP 0.9 tests
+-export([ip_get_0_9/1]).
+
+%%% Ticket tests
+-export([ticket_5775/1,ticket_5865/1,ticket_5913/1,ticket_6003/1,
+ ticket_7304/1]).
+
+%%% IPv6 tests
+-export([ipv6_hostname_ipcomm/0, ipv6_hostname_ipcomm/1,
+ ipv6_address_ipcomm/0, ipv6_address_ipcomm/1,
+ ipv6_hostname_essl/0, ipv6_hostname_essl/1,
+ ipv6_address_essl/0, ipv6_address_essl/1]).
+
+%% Help functions
+-export([cleanup_mnesia/0, setup_mnesia/0, setup_mnesia/1]).
+
+-define(IP_PORT, 8898).
+-define(SSL_PORT, 8899).
+-define(MAX_HEADER_SIZE, 256).
+-define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1").
+
+%% Minutes before failed auths timeout.
+-define(FAIL_EXPIRE_TIME,1).
+
+%% Seconds before successful auths timeout.
+-define(AUTH_TIMEOUT,5).
+
+-record(httpd_user, {user_name, password, user_data}).
+-record(httpd_group, {group_name, userlist}).
+
+
+%%--------------------------------------------------------------------
+%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
+%% Arg - doc | suite
+%% Doc - string()
+%% Case - atom()
+%% Name of a test case function.
+%% Comment - string()
+%% Description: Returns documentation/test cases in this test suite
+%% or a skip tuple if the platform is not supported.
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ {group, ip},
+ {group, ssl},
+ {group, http_1_1_ip},
+ {group, http_1_0_ip},
+ {group, http_0_9_ip},
+ {group, ipv6},
+ {group, tickets}
+ ].
+
+groups() ->
+ [
+ {ip, [],
+ [ip_mod_alias, ip_mod_actions, ip_mod_security,
+ ip_mod_auth, ip_mod_auth_api, ip_mod_auth_mnesia_api,
+ ip_mod_htaccess, ip_mod_cgi, ip_mod_esi, ip_mod_get,
+ ip_mod_head, ip_mod_all, ip_load_light, ip_load_medium,
+ ip_load_heavy, ip_dos_hostname, ip_time_test,
+ ip_restart_no_block, ip_restart_disturbing_block,
+ ip_restart_non_disturbing_block,
+ ip_block_disturbing_idle, ip_block_non_disturbing_idle,
+ ip_block_503, ip_block_disturbing_active,
+ ip_block_non_disturbing_active,
+ ip_block_disturbing_active_timeout_not_released,
+ ip_block_disturbing_active_timeout_released,
+ ip_block_non_disturbing_active_timeout_not_released,
+ ip_block_non_disturbing_active_timeout_released,
+ ip_block_disturbing_blocker_dies,
+ ip_block_non_disturbing_blocker_dies]},
+ {ssl, [], [{group, essl}]},
+ {essl, [],
+ [essl_mod_alias, essl_mod_actions, essl_mod_security,
+ essl_mod_auth, essl_mod_auth_api,
+ essl_mod_auth_mnesia_api, essl_mod_htaccess,
+ essl_mod_cgi, essl_mod_esi, essl_mod_get, essl_mod_head,
+ essl_mod_all, essl_load_light, essl_load_medium,
+ essl_load_heavy, essl_dos_hostname, essl_time_test,
+ essl_restart_no_block, essl_restart_disturbing_block,
+ essl_restart_non_disturbing_block,
+ essl_block_disturbing_idle,
+ essl_block_non_disturbing_idle, essl_block_503,
+ essl_block_disturbing_active,
+ essl_block_non_disturbing_active,
+ essl_block_disturbing_active_timeout_not_released,
+ essl_block_disturbing_active_timeout_released,
+ essl_block_non_disturbing_active_timeout_not_released,
+ essl_block_non_disturbing_active_timeout_released,
+ essl_block_disturbing_blocker_dies,
+ essl_block_non_disturbing_blocker_dies]},
+ {http_1_1_ip, [],
+ [ip_host, ip_chunked, ip_expect, ip_range, ip_if_test,
+ ip_http_trace, ip_http1_1_head,
+ ip_mod_cgi_chunked_encoding_test]},
+ {http_1_0_ip, [],
+ [ip_head_1_0, ip_get_1_0, ip_post_1_0]},
+ {http_0_9_ip, [], [ip_get_0_9]},
+ {ipv6, [], [ipv6_hostname_ipcomm, ipv6_address_ipcomm,
+ ipv6_hostname_essl, ipv6_address_essl]},
+ {tickets, [],
+ [ticket_5775, ticket_5865, ticket_5913, ticket_6003,
+ ticket_7304]}].
+
+
+init_per_group(ipv6 = _GroupName, Config) ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
+ Config;
+ _ ->
+ {skip, "Host does not support IPv6"}
+ end;
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initiation before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ io:format(user, "init_per_suite -> entry with"
+ "~n Config: ~p"
+ "~n", [Config]),
+
+ ?PRINT_SYSTEM_INFO([]),
+
+ PrivDir = ?config(priv_dir, Config),
+ SuiteTopDir = filename:join(PrivDir, ?MODULE),
+ case file:make_dir(SuiteTopDir) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ Error ->
+ throw({error, {failed_creating_suite_top_dir, Error}})
+ end,
+
+ [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
+ {suite_top_dir, SuiteTopDir},
+ {node, node()},
+ {host, inets_test_lib:hostname()},
+ {address, getaddr()} | Config].
+
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+
+end_per_suite(_Config) ->
+ %% SuiteTopDir = ?config(suite_top_dir, Config),
+ %% inets_test_lib:del_dirs(SuiteTopDir),
+ ok.
+
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(Case, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initiation before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_testcase(Case, Config) ->
+ NewConfig = init_per_testcase2(Case, Config),
+ init_per_testcase3(Case, NewConfig).
+
+
+init_per_testcase2(Case, Config) ->
+
+ %% tsp("init_per_testcase2 -> entry with"
+ %% "~n Config: ~p", [Config]),
+
+ IpNormal = integer_to_list(?IP_PORT) ++ ".conf",
+ IpHtaccess = integer_to_list(?IP_PORT) ++ "htaccess.conf",
+ SslNormal = integer_to_list(?SSL_PORT) ++ ".conf",
+ SslHtaccess = integer_to_list(?SSL_PORT) ++ "htaccess.conf",
+
+ DataDir = ?config(data_dir, Config),
+ SuiteTopDir = ?config(suite_top_dir, Config),
+
+ %% tsp("init_per_testcase2 -> "
+ %% "~n SuiteDir: ~p"
+ %% "~n DataDir: ~p", [SuiteTopDir, DataDir]),
+
+ TcTopDir = filename:join(SuiteTopDir, Case),
+ ?line ok = file:make_dir(TcTopDir),
+
+ %% tsp("init_per_testcase2 -> "
+ %% "~n TcTopDir: ~p", [TcTopDir]),
+
+ DataSrc = filename:join([DataDir, "server_root"]),
+ ServerRoot = filename:join([TcTopDir, "server_root"]),
+
+ %% tsp("init_per_testcase2 -> "
+ %% "~n DataSrc: ~p"
+ %% "~n ServerRoot: ~p", [DataSrc, ServerRoot]),
+
+ ok = file:make_dir(ServerRoot),
+ ok = file:make_dir(filename:join([TcTopDir, "logs"])),
+
+ NewConfig = [{tc_top_dir, TcTopDir}, {server_root, ServerRoot} | Config],
+
+ %% tsp("init_per_testcase2 -> copy DataSrc to ServerRoot"),
+
+ inets_test_lib:copy_dirs(DataSrc, ServerRoot),
+
+ %% tsp("init_per_testcase2 -> fix cgi"),
+ EnvCGI = filename:join([ServerRoot, "cgi-bin", "printenv.sh"]),
+ {ok, FileInfo} = file:read_file_info(EnvCGI),
+ ok = file:write_file_info(EnvCGI,
+ FileInfo#file_info{mode = 8#00755}),
+
+ EchoCGI = case test_server:os_type() of
+ {win32, _} ->
+ "cgi_echo.exe";
+ _ ->
+ "cgi_echo"
+ end,
+ CGIDir = filename:join([ServerRoot, "cgi-bin"]),
+ inets_test_lib:copy_file(EchoCGI, DataDir, CGIDir),
+ NewEchoCGI = filename:join([CGIDir, EchoCGI]),
+ {ok, FileInfo1} = file:read_file_info(NewEchoCGI),
+ ok = file:write_file_info(NewEchoCGI,
+ FileInfo1#file_info{mode = 8#00755}),
+
+ %% To be used by IP test cases
+ %% tsp("init_per_testcase2 -> ip testcase setups"),
+ create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
+ normal_access, IpNormal),
+ create_config([{port, ?IP_PORT}, {sock_type, ip_comm} | NewConfig],
+ mod_htaccess, IpHtaccess),
+
+ %% To be used by SSL test cases
+ %% tsp("init_per_testcase2 -> ssl testcase setups"),
+ SocketType =
+ case atom_to_list(Case) of
+ [X, $s, $s, $l | _] ->
+ case X of
+ $p -> ssl;
+ $e -> essl
+ end;
+ _ ->
+ ssl
+ end,
+
+ create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
+ normal_access, SslNormal),
+ create_config([{port, ?SSL_PORT}, {sock_type, SocketType} | NewConfig],
+ mod_htaccess, SslHtaccess),
+
+ %% To be used by IPv6 test cases. Case-clause is so that
+ %% you can do ts:run(inets, httpd_SUITE, <test case>)
+ %% for all cases except the ipv6 cases as they depend
+ %% on 'test_host_ipv6_only' that will only be present
+ %% when you run the whole test suite due to shortcomings
+ %% of the test server.
+
+ tsp("init_per_testcase2 -> maybe generate IPv6 config file(s)"),
+ NewConfig2 =
+ case atom_to_list(Case) of
+ "ipv6_" ++ _ ->
+ case (catch inets_test_lib:has_ipv6_support(NewConfig)) of
+ {ok, IPv6Address0} ->
+ {ok, Hostname} = inet:gethostname(),
+ IPv6Address = http_transport:ipv6_name(IPv6Address0),
+ create_ipv6_config([{port, ?IP_PORT},
+ {sock_type, ip_comm},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_hostname_ipcomm.conf",
+ Hostname),
+ create_ipv6_config([{port, ?IP_PORT},
+ {sock_type, ip_comm},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_address_ipcomm.conf",
+ IPv6Address),
+ create_ipv6_config([{port, ?SSL_PORT},
+ {sock_type, essl},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_hostname_essl.conf",
+ Hostname),
+ create_ipv6_config([{port, ?SSL_PORT},
+ {sock_type, essl},
+ {ipv6_host, IPv6Address} |
+ NewConfig],
+ "ipv6_address_essl.conf",
+ IPv6Address),
+ [{ipv6_host, IPv6Address} | NewConfig];
+ _ ->
+ NewConfig
+ end;
+
+ _ ->
+ NewConfig
+ end,
+
+ %% tsp("init_per_testcase2 -> done when"
+ %% "~n NewConfig2: ~p", [NewConfig2]),
+
+ NewConfig2.
+
+
+init_per_testcase3(Case, Config) ->
+ tsp("init_per_testcase3(~w) -> entry with"
+ "~n Config: ~p", [Case, Config]),
+
+
+%% %% Create a new fresh node to be used by the server in this test-case
+
+%% NodeName = list_to_atom(atom_to_list(Case) ++ "_httpd"),
+%% Node = inets_test_lib:start_node(NodeName),
+
+ %% Clean up (we do not want this clean up in end_per_testcase
+ %% if init_per_testcase crashes for some testcase it will
+ %% have contaminated the environment and there will be no clean up.)
+ %% This init can take a few different paths so that one crashes
+ %% does not mean that all invocations will.
+
+ application:unset_env(inets, services),
+ application:stop(inets),
+ application:stop(ssl),
+ cleanup_mnesia(),
+
+ %% Start initialization
+ tsp("init_per_testcase3(~w) -> start init", [Case]),
+
+ Dog = test_server:timetrap(inets_test_lib:minutes(10)),
+ NewConfig = lists:keydelete(watchdog, 1, Config),
+ TcTopDir = ?config(tc_top_dir, Config),
+
+ CaseRest =
+ case atom_to_list(Case) of
+ "ip_mod_htaccess" ->
+ inets_test_lib:start_http_server(
+ filename:join(TcTopDir,
+ integer_to_list(?IP_PORT) ++
+ "htaccess.conf")),
+ "mod_htaccess";
+ "ip_" ++ Rest ->
+ inets_test_lib:start_http_server(
+ filename:join(TcTopDir,
+ integer_to_list(?IP_PORT) ++ ".conf")),
+ Rest;
+ "ticket_5913" ->
+ HttpdOptions =
+ [{file,
+ filename:join(TcTopDir,
+ integer_to_list(?IP_PORT) ++ ".conf")},
+ {accept_timeout,30000},
+ {debug,[{exported_functions,
+ [httpd_manager,httpd_request_handler]}]}],
+ inets_test_lib:start_http_server(HttpdOptions);
+ "ticket_"++Rest ->
+ %% OTP-5913 use the new syntax of inets.config
+ inets_test_lib:start_http_server([{file,
+ filename:join(TcTopDir,
+ integer_to_list(?IP_PORT) ++ ".conf")}]),
+ Rest;
+
+ [X, $s, $s, $l, $_, $m, $o, $d, $_, $h, $t, $a, $c, $c, $e, $s, $s] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
+ SslTag =
+ case X of
+ $p -> ssl; % Plain
+ $e -> essl % Erlang based ssl
+ end,
+ case inets_test_lib:start_http_server_ssl(
+ filename:join(TcTopDir,
+ integer_to_list(?SSL_PORT) ++
+ "htaccess.conf"), SslTag) of
+ ok ->
+ "mod_htaccess";
+ Other ->
+ error_logger:info_msg("Other: ~p~n", [Other]),
+ {skip, "SSL does not seem to be supported"}
+ end;
+ [X, $s, $s, $l, $_ | Rest] ->
+ ?ENSURE_STARTED([crypto, public_key, ssl]),
+ SslTag =
+ case X of
+ $p -> ssl;
+ $e -> essl
+ end,
+ case inets_test_lib:start_http_server_ssl(
+ filename:join(TcTopDir,
+ integer_to_list(?SSL_PORT) ++
+ ".conf"), SslTag) of
+ ok ->
+ Rest;
+ Other ->
+ error_logger:info_msg("Other: ~p~n", [Other]),
+ {skip, "SSL does not seem to be supported"}
+ end;
+ "ipv6_" ++ _ = TestCaseStr ->
+ case inets_test_lib:has_ipv6_support() of
+ {ok, _} ->
+ inets_test_lib:start_http_server(
+ filename:join(TcTopDir,
+ TestCaseStr ++ ".conf"));
+
+ _ ->
+ {skip, "Host does not support IPv6"}
+ end
+ end,
+
+ InitRes =
+ case CaseRest of
+ {skip, _} = Skip ->
+ Skip;
+ "mod_auth_" ++ _ ->
+ start_mnesia(?config(node, Config)),
+ [{watchdog, Dog} | NewConfig];
+ "mod_htaccess" ->
+ ServerRoot = ?config(server_root, Config),
+ Path = filename:join([ServerRoot, "htdocs"]),
+ catch remove_htaccess(Path),
+ create_htaccess_data(Path, ?config(address, Config)),
+ [{watchdog, Dog} | NewConfig];
+ "range" ->
+ ServerRoot = ?config(server_root, Config),
+ Path = filename:join([ServerRoot, "htdocs"]),
+ create_range_data(Path),
+ [{watchdog, Dog} | NewConfig];
+ _ ->
+ [{watchdog, Dog} | NewConfig]
+ end,
+
+ tsp("init_per_testcase3(~w) -> done when"
+ "~n InitRes: ~p", [Case, InitRes]),
+
+ InitRes.
+
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(Case, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ test_server:timetrap_cancel(Dog),
+ end_per_testcase2(Case, lists:keydelete(watchdog, 1, Config)),
+ ok.
+
+end_per_testcase2(Case, Config) ->
+ tsp("end_per_testcase2(~w) -> entry with"
+ "~n Config: ~p", [Case, Config]),
+ application:unset_env(inets, services),
+ application:stop(inets),
+ application:stop(ssl),
+ application:stop(crypto), % used by the new ssl (essl test cases)
+ cleanup_mnesia(),
+ tsp("end_per_testcase2(~w) -> done", [Case]),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
+
+%%-------------------------------------------------------------------------
+ip_mod_alias(doc) ->
+ ["Module test: mod_alias"];
+ip_mod_alias(suite) ->
+ [];
+ip_mod_alias(Config) when is_list(Config) ->
+ httpd_mod:alias(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_mod_actions(doc) ->
+ ["Module test: mod_actions"];
+ip_mod_actions(suite) ->
+ [];
+ip_mod_actions(Config) when is_list(Config) ->
+ httpd_mod:actions(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_mod_security(doc) ->
+ ["Module test: mod_security"];
+ip_mod_security(suite) ->
+ [];
+ip_mod_security(Config) when is_list(Config) ->
+ ServerRoot = ?config(server_root, Config),
+ httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_mod_auth(doc) ->
+ ["Module test: mod_auth"];
+ip_mod_auth(suite) ->
+ [];
+ip_mod_auth(Config) when is_list(Config) ->
+ httpd_mod:auth(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_mod_auth_api(doc) ->
+ ["Module test: mod_auth_api"];
+ip_mod_auth_api(suite) ->
+ [];
+ip_mod_auth_api(Config) when is_list(Config) ->
+ ServerRoot = ?config(server_root, Config),
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ httpd_mod:auth_api(ServerRoot, "", ip_comm, ?IP_PORT, Host, Node),
+ httpd_mod:auth_api(ServerRoot, "dets_", ip_comm, ?IP_PORT, Host, Node),
+ httpd_mod:auth_api(ServerRoot, "mnesia_", ip_comm, ?IP_PORT, Host, Node),
+ ok.
+%%-------------------------------------------------------------------------
+ip_mod_auth_mnesia_api(doc) ->
+ ["Module test: mod_auth_mnesia_api"];
+ip_mod_auth_mnesia_api(suite) ->
+ [];
+ip_mod_auth_mnesia_api(Config) when is_list(Config) ->
+ httpd_mod:auth_mnesia_api(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_mod_htaccess(doc) ->
+ ["Module test: mod_htaccess"];
+ip_mod_htaccess(suite) ->
+ [];
+ip_mod_htaccess(Config) when is_list(Config) ->
+ httpd_mod:htaccess(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_mod_cgi(doc) ->
+ ["Module test: mod_cgi"];
+ip_mod_cgi(suite) ->
+ [];
+ip_mod_cgi(Config) when is_list(Config) ->
+ httpd_mod:cgi(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_mod_esi(doc) ->
+ ["Module test: mod_esi"];
+ip_mod_esi(suite) ->
+ [];
+ip_mod_esi(Config) when is_list(Config) ->
+ httpd_mod:esi(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_mod_get(doc) ->
+ ["Module test: mod_get"];
+ip_mod_get(suite) ->
+ [];
+ip_mod_get(Config) when is_list(Config) ->
+ httpd_mod:get(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_mod_head(doc) ->
+ ["Module test: mod_head"];
+ip_mod_head(suite) ->
+ [];
+ip_mod_head(Config) when is_list(Config) ->
+ httpd_mod:head(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_mod_all(doc) ->
+ ["All modules test"];
+ip_mod_all(suite) ->
+ [];
+ip_mod_all(Config) when is_list(Config) ->
+ httpd_mod:all(ip_comm, ?IP_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_load_light(doc) ->
+ ["Test light load"];
+ip_load_light(suite) ->
+ [];
+ip_load_light(Config) when is_list(Config) ->
+ httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config),
+ get_nof_clients(ip_comm, light)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_load_medium(doc) ->
+ ["Test medium load"];
+ip_load_medium(suite) ->
+ [];
+ip_load_medium(Config) when is_list(Config) ->
+ httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config),
+ get_nof_clients(ip_comm, medium)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_load_heavy(doc) ->
+ ["Test heavy load"];
+ip_load_heavy(suite) ->
+ [];
+ip_load_heavy(Config) when is_list(Config) ->
+ httpd_load:load_test(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config),
+ get_nof_clients(ip_comm, heavy)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+ip_dos_hostname(doc) ->
+ ["Denial Of Service (DOS) attack test case"];
+ip_dos_hostname(suite) ->
+ [];
+ip_dos_hostname(Config) when is_list(Config) ->
+ dos_hostname(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config), ?MAX_HEADER_SIZE),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+ip_time_test(doc) ->
+ [""];
+ip_time_test(suite) ->
+ [];
+ip_time_test(Config) when is_list(Config) ->
+ %% <CONDITIONAL-SKIP>
+ Skippable = [win32],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_time_test:t(ip_comm, ?config(host, Config), ?IP_PORT),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_block_503(doc) ->
+ ["Check that you will receive status code 503 when the server"
+ " is blocked and 200 when its not blocked."];
+ip_block_503(suite) ->
+ [];
+ip_block_503(Config) when is_list(Config) ->
+ httpd_block:block_503(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_disturbing_idle(doc) ->
+ ["Check that you can block/unblock an idle server. The strategy "
+ "distribing does not really make a difference in this case."];
+ip_block_disturbing_idle(suite) ->
+ [];
+ip_block_disturbing_idle(Config) when is_list(Config) ->
+ httpd_block:block_disturbing_idle(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_non_disturbing_idle(doc) ->
+ ["Check that you can block/unblock an idle server. The strategy "
+ "non distribing does not really make a difference in this case."];
+ip_block_non_disturbing_idle(suite) ->
+ [];
+ip_block_non_disturbing_idle(Config) when is_list(Config) ->
+ httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_disturbing_active(doc) ->
+ ["Check that you can block/unblock an active server. The strategy "
+ "distribing means ongoing requests should be terminated."];
+ip_block_disturbing_active(suite) ->
+ [];
+ip_block_disturbing_active(Config) when is_list(Config) ->
+ httpd_block:block_disturbing_active(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_non_disturbing_active(doc) ->
+ ["Check that you can block/unblock an idle server. The strategy "
+ "non distribing means the ongoing requests should be compleated."];
+ip_block_non_disturbing_active(suite) ->
+ [];
+ip_block_non_disturbing_active(Config) when is_list(Config) ->
+ httpd_block:block_non_disturbing_idle(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_block_disturbing_active_timeout_not_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "distribing means ongoing requests should be compleated"
+ "if the timeout does not occur."];
+ip_block_disturbing_active_timeout_not_released(suite) ->
+ [];
+ip_block_disturbing_active_timeout_not_released(Config)
+ when is_list(Config) ->
+ httpd_block:block_disturbing_active_timeout_not_released(ip_comm,
+ ?IP_PORT,
+ ?config(host,
+ Config),
+ ?config(node,
+ Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_disturbing_active_timeout_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "distribing means ongoing requests should be terminated when"
+ "the timeout occurs."];
+ip_block_disturbing_active_timeout_released(suite) ->
+ [];
+ip_block_disturbing_active_timeout_released(Config)
+ when is_list(Config) ->
+ httpd_block:block_disturbing_active_timeout_released(ip_comm,
+ ?IP_PORT,
+ ?config(host,
+ Config),
+ ?config(node,
+ Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_block_non_disturbing_active_timeout_not_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "non non distribing means ongoing requests should be completed."];
+ip_block_non_disturbing_active_timeout_not_released(suite) ->
+ [];
+ip_block_non_disturbing_active_timeout_not_released(Config)
+ when is_list(Config) ->
+ httpd_block:
+ block_non_disturbing_active_timeout_not_released(ip_comm,
+ ?IP_PORT,
+ ?config(host,
+ Config),
+ ?config(node,
+ Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_non_disturbing_active_timeout_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "non non distribing means ongoing requests should be completed. "
+ "When the timeout occurs the block operation sohould be canceled." ];
+ip_block_non_disturbing_active_timeout_released(suite) ->
+ [];
+ip_block_non_disturbing_active_timeout_released(Config)
+ when is_list(Config) ->
+ httpd_block:
+ block_non_disturbing_active_timeout_released(ip_comm,
+ ?IP_PORT,
+ ?config(host,
+ Config),
+ ?config(node,
+ Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_disturbing_blocker_dies(doc) ->
+ [];
+ip_block_disturbing_blocker_dies(suite) ->
+ [];
+ip_block_disturbing_blocker_dies(Config) when is_list(Config) ->
+ httpd_block:disturbing_blocker_dies(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_block_non_disturbing_blocker_dies(doc) ->
+ [];
+ip_block_non_disturbing_blocker_dies(suite) ->
+ [];
+ip_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
+ httpd_block:non_disturbing_blocker_dies(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_restart_no_block(doc) ->
+ [""];
+ip_restart_no_block(suite) ->
+ [];
+ip_restart_no_block(Config) when is_list(Config) ->
+ httpd_block:restart_no_block(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_restart_disturbing_block(doc) ->
+ [""];
+ip_restart_disturbing_block(suite) ->
+ [];
+ip_restart_disturbing_block(Config) when is_list(Config) ->
+ %% <CONDITIONAL-SKIP>
+ Condition =
+ fun() ->
+ case os:type() of
+ {unix, linux} ->
+ HW = string:strip(os:cmd("uname -m"), right, $\n),
+ case HW of
+ "ppc" ->
+ case inet:gethostname() of
+ {ok, "peach"} ->
+ true;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end
+ end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_block:restart_disturbing_block(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_restart_non_disturbing_block(doc) ->
+ [""];
+ip_restart_non_disturbing_block(suite) ->
+ [];
+ip_restart_non_disturbing_block(Config) when is_list(Config) ->
+ %% <CONDITIONAL-SKIP>
+ Condition =
+ fun() ->
+ case os:type() of
+ {unix, linux} ->
+ HW = string:strip(os:cmd("uname -m"), right, $\n),
+ case HW of
+ "ppc" ->
+ case inet:gethostname() of
+ {ok, "peach"} ->
+ true;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end
+ end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_block:restart_non_disturbing_block(ip_comm, ?IP_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+
+essl_mod_alias(doc) ->
+ ["Module test: mod_alias - using new of configure new SSL"];
+essl_mod_alias(suite) ->
+ [];
+essl_mod_alias(Config) when is_list(Config) ->
+ ssl_mod_alias(essl, Config).
+
+
+ssl_mod_alias(Tag, Config) ->
+ httpd_mod:alias(Tag, ?SSL_PORT,
+ ?config(host, Config), ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_actions(doc) ->
+ ["Module test: mod_actions - using new of configure new SSL"];
+essl_mod_actions(suite) ->
+ [];
+essl_mod_actions(Config) when is_list(Config) ->
+ ssl_mod_actions(essl, Config).
+
+
+ssl_mod_actions(Tag, Config) ->
+ httpd_mod:actions(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_security(doc) ->
+ ["Module test: mod_security - using new of configure new SSL"];
+essl_mod_security(suite) ->
+ [];
+essl_mod_security(Config) when is_list(Config) ->
+ ssl_mod_security(essl, Config).
+
+ssl_mod_security(Tag, Config) ->
+ ServerRoot = ?config(server_root, Config),
+ httpd_mod:security(ServerRoot,
+ Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_auth(doc) ->
+ ["Module test: mod_auth - using new of configure new SSL"];
+essl_mod_auth(suite) ->
+ [];
+essl_mod_auth(Config) when is_list(Config) ->
+ ssl_mod_auth(essl, Config).
+
+ssl_mod_auth(Tag, Config) ->
+ httpd_mod:auth(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_mod_auth_api(doc) ->
+ ["Module test: mod_auth - using new of configure new SSL"];
+essl_mod_auth_api(suite) ->
+ [];
+essl_mod_auth_api(Config) when is_list(Config) ->
+ ssl_mod_auth_api(essl, Config).
+
+ssl_mod_auth_api(Tag, Config) ->
+ ServerRoot = ?config(server_root, Config),
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ httpd_mod:auth_api(ServerRoot, "", Tag, ?SSL_PORT, Host, Node),
+ httpd_mod:auth_api(ServerRoot, "dets_", Tag, ?SSL_PORT, Host, Node),
+ httpd_mod:auth_api(ServerRoot, "mnesia_", Tag, ?SSL_PORT, Host, Node),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_mod_auth_mnesia_api(doc) ->
+ ["Module test: mod_auth_mnesia_api - using new of configure new SSL"];
+essl_mod_auth_mnesia_api(suite) ->
+ [];
+essl_mod_auth_mnesia_api(Config) when is_list(Config) ->
+ ssl_mod_auth_mnesia_api(essl, Config).
+
+ssl_mod_auth_mnesia_api(Tag, Config) ->
+ httpd_mod:auth_mnesia_api(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_htaccess(doc) ->
+ ["Module test: mod_htaccess - using new of configure new SSL"];
+essl_mod_htaccess(suite) ->
+ [];
+essl_mod_htaccess(Config) when is_list(Config) ->
+ ssl_mod_htaccess(essl, Config).
+
+ssl_mod_htaccess(Tag, Config) ->
+ httpd_mod:htaccess(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_cgi(doc) ->
+ ["Module test: mod_cgi - using new of configure new SSL"];
+essl_mod_cgi(suite) ->
+ [];
+essl_mod_cgi(Config) when is_list(Config) ->
+ ssl_mod_cgi(essl, Config).
+
+ssl_mod_cgi(Tag, Config) ->
+ httpd_mod:cgi(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_esi(doc) ->
+ ["Module test: mod_esi - using new of configure new SSL"];
+essl_mod_esi(suite) ->
+ [];
+essl_mod_esi(Config) when is_list(Config) ->
+ ssl_mod_esi(essl, Config).
+
+ssl_mod_esi(Tag, Config) ->
+ httpd_mod:esi(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_get(doc) ->
+ ["Module test: mod_get - using new of configure new SSL"];
+essl_mod_get(suite) ->
+ [];
+essl_mod_get(Config) when is_list(Config) ->
+ ssl_mod_get(essl, Config).
+
+ssl_mod_get(Tag, Config) ->
+ httpd_mod:get(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_head(doc) ->
+ ["Module test: mod_head - using new of configure new SSL"];
+essl_mod_head(suite) ->
+ [];
+essl_mod_head(Config) when is_list(Config) ->
+ ssl_mod_head(essl, Config).
+
+ssl_mod_head(Tag, Config) ->
+ httpd_mod:head(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_mod_all(doc) ->
+ ["All modules test - using new of configure new SSL"];
+essl_mod_all(suite) ->
+ [];
+essl_mod_all(Config) when is_list(Config) ->
+ ssl_mod_all(essl, Config).
+
+ssl_mod_all(Tag, Config) ->
+ httpd_mod:all(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_load_light(doc) ->
+ ["Test light load - using new of configure new SSL"];
+essl_load_light(suite) ->
+ [];
+essl_load_light(Config) when is_list(Config) ->
+ ssl_load_light(essl, Config).
+
+ssl_load_light(Tag, Config) ->
+ httpd_load:load_test(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config),
+ get_nof_clients(ssl, light)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_load_medium(doc) ->
+ ["Test medium load - using new of configure new SSL"];
+essl_load_medium(suite) ->
+ [];
+essl_load_medium(Config) when is_list(Config) ->
+ ssl_load_medium(essl, Config).
+
+ssl_load_medium(Tag, Config) ->
+ %% <CONDITIONAL-SKIP>
+ Skippable = [win32],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_load:load_test(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config),
+ get_nof_clients(ssl, medium)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_load_heavy(doc) ->
+ ["Test heavy load - using new of configure new SSL"];
+essl_load_heavy(suite) ->
+ [];
+essl_load_heavy(Config) when is_list(Config) ->
+ ssl_load_heavy(essl, Config).
+
+ssl_load_heavy(Tag, Config) ->
+ %% <CONDITIONAL-SKIP>
+ Skippable = [win32],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_load:load_test(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config),
+ get_nof_clients(ssl, heavy)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_dos_hostname(doc) ->
+ ["Denial Of Service (DOS) attack test case - using new of configure new SSL"];
+essl_dos_hostname(suite) ->
+ [];
+essl_dos_hostname(Config) when is_list(Config) ->
+ ssl_dos_hostname(essl, Config).
+
+ssl_dos_hostname(Tag, Config) ->
+ dos_hostname(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config),
+ ?MAX_HEADER_SIZE),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_time_test(doc) ->
+ ["using new of configure new SSL"];
+essl_time_test(suite) ->
+ [];
+essl_time_test(Config) when is_list(Config) ->
+ ssl_time_test(essl, Config).
+
+ssl_time_test(Tag, Config) when is_list(Config) ->
+ %% <CONDITIONAL-SKIP>
+ FreeBSDVersionVerify =
+ fun() ->
+ case os:version() of
+ {7, 1, _} -> % We only have one such machine, so...
+ true;
+ _ ->
+ false
+ end
+ end,
+ Skippable = [win32, {unix, [{freebsd, FreeBSDVersionVerify}]}],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_time_test:t(Tag,
+ ?config(host, Config),
+ ?SSL_PORT),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_block_503(doc) ->
+ ["Check that you will receive status code 503 when the server"
+ " is blocked and 200 when its not blocked - using new of configure new SSL."];
+essl_block_503(suite) ->
+ [];
+essl_block_503(Config) when is_list(Config) ->
+ ssl_block_503(essl, Config).
+
+ssl_block_503(Tag, Config) ->
+ httpd_block:block_503(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_disturbing_idle(doc) ->
+ ["Check that you can block/unblock an idle server. The strategy "
+ "distribing does not really make a difference in this case."
+ "Using new of configure new SSL"];
+essl_block_disturbing_idle(suite) ->
+ [];
+essl_block_disturbing_idle(Config) when is_list(Config) ->
+ ssl_block_disturbing_idle(essl, Config).
+
+ssl_block_disturbing_idle(Tag, Config) ->
+ httpd_block:block_disturbing_idle(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_non_disturbing_idle(doc) ->
+ ["Check that you can block/unblock an idle server. The strategy "
+ "non distribing does not really make a difference in this case."
+ "Using new of configure new SSL"];
+essl_block_non_disturbing_idle(suite) ->
+ [];
+essl_block_non_disturbing_idle(Config) when is_list(Config) ->
+ ssl_block_non_disturbing_idle(essl, Config).
+
+ssl_block_non_disturbing_idle(Tag, Config) ->
+ httpd_block:block_non_disturbing_idle(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_disturbing_active(doc) ->
+ ["Check that you can block/unblock an active server. The strategy "
+ "distribing means ongoing requests should be terminated."
+ "Using new of configure new SSL"];
+essl_block_disturbing_active(suite) ->
+ [];
+essl_block_disturbing_active(Config) when is_list(Config) ->
+ ssl_block_disturbing_active(essl, Config).
+
+ssl_block_disturbing_active(Tag, Config) ->
+ httpd_block:block_disturbing_active(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_non_disturbing_active(doc) ->
+ ["Check that you can block/unblock an idle server. The strategy "
+ "non distribing means the ongoing requests should be compleated."
+ "Using new of configure new SSL"];
+essl_block_non_disturbing_active(suite) ->
+ [];
+essl_block_non_disturbing_active(Config) when is_list(Config) ->
+ ssl_block_non_disturbing_active(essl, Config).
+
+ssl_block_non_disturbing_active(Tag, Config) ->
+ httpd_block:block_non_disturbing_idle(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_disturbing_active_timeout_not_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "distribing means ongoing requests should be compleated"
+ "if the timeout does not occur."
+ "Using new of configure new SSL"];
+essl_block_disturbing_active_timeout_not_released(suite) ->
+ [];
+essl_block_disturbing_active_timeout_not_released(Config)
+ when is_list(Config) ->
+ ssl_block_disturbing_active_timeout_not_released(essl, Config).
+
+ssl_block_disturbing_active_timeout_not_released(Tag, Config) ->
+ Port = ?SSL_PORT,
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ httpd_block:block_disturbing_active_timeout_not_released(Tag,
+ Port, Host, Node),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_disturbing_active_timeout_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "distribing means ongoing requests should be terminated when"
+ "the timeout occurs."
+ "Using new of configure new SSL"];
+essl_block_disturbing_active_timeout_released(suite) ->
+ [];
+essl_block_disturbing_active_timeout_released(Config)
+ when is_list(Config) ->
+ ssl_block_disturbing_active_timeout_released(essl, Config).
+
+ssl_block_disturbing_active_timeout_released(Tag, Config) ->
+ Port = ?SSL_PORT,
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ httpd_block:block_disturbing_active_timeout_released(Tag,
+ Port,
+ Host,
+ Node),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_non_disturbing_active_timeout_not_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "non non distribing means ongoing requests should be completed."
+ "Using new of configure new SSL"];
+essl_block_non_disturbing_active_timeout_not_released(suite) ->
+ [];
+essl_block_non_disturbing_active_timeout_not_released(Config)
+ when is_list(Config) ->
+ ssl_block_non_disturbing_active_timeout_not_released(essl, Config).
+
+ssl_block_non_disturbing_active_timeout_not_released(Tag, Config) ->
+ Port = ?SSL_PORT,
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ httpd_block:block_non_disturbing_active_timeout_not_released(Tag,
+ Port,
+ Host,
+ Node),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_block_non_disturbing_active_timeout_released(doc) ->
+ ["Check that you can block an active server. The strategy "
+ "non distribing means ongoing requests should be completed. "
+ "When the timeout occurs the block operation sohould be canceled."
+ "Using new of configure new SSL"];
+essl_block_non_disturbing_active_timeout_released(suite) ->
+ [];
+essl_block_non_disturbing_active_timeout_released(Config)
+ when is_list(Config) ->
+ ssl_block_non_disturbing_active_timeout_released(essl, Config).
+
+ssl_block_non_disturbing_active_timeout_released(Tag, Config)
+ when is_list(Config) ->
+ Port = ?SSL_PORT,
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ httpd_block:block_non_disturbing_active_timeout_released(Tag,
+ Port,
+ Host,
+ Node),
+
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_block_disturbing_blocker_dies(doc) ->
+ ["using new of configure new SSL"];
+essl_block_disturbing_blocker_dies(suite) ->
+ [];
+essl_block_disturbing_blocker_dies(Config) when is_list(Config) ->
+ ssl_block_disturbing_blocker_dies(essl, Config).
+
+ssl_block_disturbing_blocker_dies(Tag, Config) ->
+ httpd_block:disturbing_blocker_dies(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+essl_block_non_disturbing_blocker_dies(doc) ->
+ ["using new of configure new SSL"];
+essl_block_non_disturbing_blocker_dies(suite) ->
+ [];
+essl_block_non_disturbing_blocker_dies(Config) when is_list(Config) ->
+ ssl_block_non_disturbing_blocker_dies(essl, Config).
+
+ssl_block_non_disturbing_blocker_dies(Tag, Config) ->
+ httpd_block:non_disturbing_blocker_dies(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_restart_no_block(doc) ->
+ ["using new of configure new SSL"];
+essl_restart_no_block(suite) ->
+ [];
+essl_restart_no_block(Config) when is_list(Config) ->
+ ssl_restart_no_block(essl, Config).
+
+ssl_restart_no_block(Tag, Config) ->
+ httpd_block:restart_no_block(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_restart_disturbing_block(doc) ->
+ ["using new of configure new SSL"];
+essl_restart_disturbing_block(suite) ->
+ [];
+essl_restart_disturbing_block(Config) when is_list(Config) ->
+ ssl_restart_disturbing_block(essl, Config).
+
+ssl_restart_disturbing_block(Tag, Config) ->
+ %% <CONDITIONAL-SKIP>
+ Condition =
+ fun() ->
+ case os:type() of
+ {unix, linux} ->
+ case ?OSCMD("uname -m") of
+ "ppc" ->
+ case file:read_file_info("/etc/fedora-release") of
+ {ok, _} ->
+ case ?OSCMD("awk '{print $2}' /etc/fedora-release") of
+ "release" ->
+ %% Fedora 7 and later
+ case ?OSCMD("awk '{print $3}' /etc/fedora-release") of
+ "7" ->
+ true;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end
+ end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_block:restart_disturbing_block(Tag, ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+
+
+essl_restart_non_disturbing_block(doc) ->
+ ["using new of configure new SSL"];
+essl_restart_non_disturbing_block(suite) ->
+ [];
+essl_restart_non_disturbing_block(Config) when is_list(Config) ->
+ ssl_restart_non_disturbing_block(essl, Config).
+
+ssl_restart_non_disturbing_block(Tag, Config) ->
+ %% <CONDITIONAL-SKIP>
+ Condition =
+ fun() ->
+ case os:type() of
+ {unix, linux} ->
+ HW = string:strip(os:cmd("uname -m"), right, $\n),
+ case HW of
+ "ppc" ->
+ case inet:gethostname() of
+ {ok, "peach"} ->
+ true;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end
+ end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ httpd_block:restart_non_disturbing_block(Tag,
+ ?SSL_PORT,
+ ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+
+%%-------------------------------------------------------------------------
+ip_host(doc) ->
+ ["Control that the server accepts/rejects requests with/ without host"];
+ip_host(suite)->
+ [];
+ip_host(Config) when is_list(Config) ->
+ httpd_1_1:host(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_chunked(doc) ->
+ ["Control that the server accepts chunked requests"];
+ip_chunked(suite) ->
+ [];
+ip_chunked(Config) when is_list(Config) ->
+ httpd_1_1:chunked(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_expect(doc) ->
+ ["Control that the server handles request with the expect header "
+ "field appropiate"];
+ip_expect(suite)->
+ [];
+ip_expect(Config) when is_list(Config) ->
+ httpd_1_1:expect(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_range(doc) ->
+ ["Control that the server can handle range requests to plain files"];
+ip_range(suite)->
+ [];
+ip_range(Config) when is_list(Config) ->
+ httpd_1_1:range(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_if_test(doc) ->
+ ["Test that the if - request header fields is handled correclty"];
+ip_if_test(suite) ->
+ [];
+ip_if_test(Config) when is_list(Config) ->
+ ServerRoot = ?config(server_root, Config),
+ DocRoot = filename:join([ServerRoot, "htdocs"]),
+ httpd_1_1:if_test(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config), DocRoot),
+ ok.
+%%-------------------------------------------------------------------------
+ip_http_trace(doc) ->
+ ["Test the trace module "];
+ip_http_trace(suite) ->
+ [];
+ip_http_trace(Config) when is_list(Config) ->
+ httpd_1_1:http_trace(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+%%-------------------------------------------------------------------------
+ip_http1_1_head(doc) ->
+ ["Test the trace module "];
+ip_http1_1_head(suite)->
+ [];
+ip_http1_1_head(Config) when is_list(Config) ->
+ httpd_1_1:head(ip_comm, ?IP_PORT, ?config(host, Config),
+ ?config(node, Config)),
+ ok.
+
+%%-------------------------------------------------------------------------
+ip_get_0_9(doc) ->
+ ["Test simple HTTP/0.9 GET"];
+ip_get_0_9(suite)->
+ [];
+ip_get_0_9(Config) when is_list(Config) ->
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
+ "GET / \r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/0.9"} ]),
+ %% Without space after uri
+ ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
+ "GET /\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/0.9"} ]),
+ ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
+ "GET / HTTP/0.9\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/0.9"}]),
+
+ ok.
+%%-------------------------------------------------------------------------
+ip_head_1_0(doc) ->
+ ["Test HTTP/1.0 HEAD"];
+ip_head_1_0(suite)->
+ [];
+ip_head_1_0(Config) when is_list(Config) ->
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
+ "HEAD / HTTP/1.0\r\n\r\n", [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ ok.
+%%-------------------------------------------------------------------------
+ip_get_1_0(doc) ->
+ ["Test HTTP/1.0 GET"];
+ip_get_1_0(suite)->
+ [];
+ip_get_1_0(Config) when is_list(Config) ->
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
+ "GET / HTTP/1.0\r\n\r\n", [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+
+ ok.
+%%-------------------------------------------------------------------------
+ip_post_1_0(doc) ->
+ ["Test HTTP/1.0 POST"];
+ip_post_1_0(suite)->
+ [];
+ip_post_1_0(Config) when is_list(Config) ->
+ Host = ?config(host, Config),
+ Node = ?config(node, Config),
+ %% Test the post message formatin 1.0! Real post are testes elsewhere
+ ok = httpd_test_lib:verify_request(ip_comm, Host, ?IP_PORT, Node,
+ "POST / HTTP/1.0\r\n\r\n "
+ "Content-Length:6 \r\n\r\nfoobar",
+ [{statuscode, 500}, {version, "HTTP/1.0"}]),
+
+ ok.
+%%-------------------------------------------------------------------------
+ip_mod_cgi_chunked_encoding_test(doc) ->
+ ["Test the trace module "];
+ip_mod_cgi_chunked_encoding_test(suite)->
+ [];
+ip_mod_cgi_chunked_encoding_test(Config) when is_list(Config) ->
+ Host = ?config(host, Config),
+ Script =
+ case test_server:os_type() of
+ {win32, _} ->
+ "/cgi-bin/printenv.bat";
+ _ ->
+ "/cgi-bin/printenv.sh"
+ end,
+ Requests =
+ ["GET " ++ Script ++ " HTTP/1.1\r\nHost:"++ Host ++"\r\n\r\n",
+ "GET /cgi-bin/erl/httpd_example/newformat HTTP/1.1\r\nHost:"
+ ++ Host ++"\r\n\r\n"],
+ httpd_1_1:mod_cgi_chunked_encoding_test(ip_comm, ?IP_PORT,
+ Host,
+ ?config(node, Config),
+ Requests),
+ ok.
+
+%-------------------------------------------------------------------------
+
+ipv6_hostname_ipcomm() ->
+ [{require, ipv6_hosts}].
+ipv6_hostname_ipcomm(X) ->
+ SocketType = ip_comm,
+ Port = ?IP_PORT,
+ ipv6_hostname(SocketType, Port, X).
+
+ipv6_hostname_essl() ->
+ [{require, ipv6_hosts}].
+ipv6_hostname_essl(X) ->
+ SocketType = essl,
+ Port = ?SSL_PORT,
+ ipv6_hostname(SocketType, Port, X).
+
+ipv6_hostname(_SocketType, _Port, doc) ->
+ ["Test standard ipv6 address"];
+ipv6_hostname(_SocketType, _Port, suite)->
+ [];
+ipv6_hostname(SocketType, Port, Config) when is_list(Config) ->
+ tsp("ipv6_hostname -> entry with"
+ "~n SocketType: ~p"
+ "~n Port: ~p"
+ "~n Config: ~p", [SocketType, Port, Config]),
+ Host = ?config(host, Config),
+ URI = "GET HTTP://" ++
+ Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
+ tsp("ipv6_hostname -> Host: ~p", [Host]),
+ httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
+ node(),
+ URI,
+ [{statuscode, 200}, {version, "HTTP/1.1"}]),
+ ok.
+
+%%-------------------------------------------------------------------------
+
+ipv6_address_ipcomm() ->
+ [{require, ipv6_hosts}].
+ipv6_address_ipcomm(X) ->
+ SocketType = ip_comm,
+ Port = ?IP_PORT,
+ ipv6_address(SocketType, Port, X).
+
+ipv6_address_essl() ->
+ [{require, ipv6_hosts}].
+ipv6_address_essl(X) ->
+ SocketType = essl,
+ Port = ?SSL_PORT,
+ ipv6_address(SocketType, Port, X).
+
+ipv6_address(_SocketType, _Port, doc) ->
+ ["Test standard ipv6 address"];
+ipv6_address(_SocketType, _Port, suite)->
+ [];
+ipv6_address(SocketType, Port, Config) when is_list(Config) ->
+ tsp("ipv6_address -> entry with"
+ "~n SocketType: ~p"
+ "~n Port: ~p"
+ "~n Config: ~p", [SocketType, Port, Config]),
+ Host = ?config(host, Config),
+ tsp("ipv6_address -> Host: ~p", [Host]),
+ URI = "GET HTTP://" ++
+ Host ++ ":" ++ integer_to_list(Port) ++ "/ HTTP/1.1\r\n\r\n",
+ httpd_test_lib:verify_request(SocketType, Host, Port, [inet6],
+ node(),
+ URI,
+ [{statuscode, 200}, {version, "HTTP/1.1"}]),
+ ok.
+
+
+%%--------------------------------------------------------------------
+ticket_5775(doc) ->
+ ["Tests that content-length is correct"];
+ticket_5775(suite) ->
+ [];
+ticket_5775(Config) ->
+ ok=httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
+ "GET /cgi-bin/erl/httpd_example:get_bin "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok.
+ticket_5865(doc) ->
+ ["Tests that a header without last-modified is handled"];
+ticket_5865(suite) ->
+ [];
+ticket_5865(Config) ->
+ ?SKIP(as_of_r15_behaviour_of_calendar_has_changed),
+ Host = ?config(host,Config),
+ ServerRoot = ?config(server_root, Config),
+ DocRoot = filename:join([ServerRoot, "htdocs"]),
+ File = filename:join([DocRoot,"last_modified.html"]),
+
+ Bad_mtime = case test_server:os_type() of
+ {win32, _} ->
+ {{1600,12,31},{23,59,59}};
+ {unix, _} ->
+ {{1969,12,31},{23,59,59}}
+ end,
+
+ {ok,FI}=file:read_file_info(File),
+
+ case file:write_file_info(File,FI#file_info{mtime=Bad_mtime}) of
+ ok ->
+ ok = httpd_test_lib:verify_request(ip_comm, Host,
+ ?IP_PORT, ?config(node, Config),
+ "GET /last_modified.html"
+ " HTTP/1.1\r\nHost:"
+ ++Host++"\r\n\r\n",
+ [{statuscode, 200},
+ {no_header,
+ "last-modified"}]),
+ ok;
+ {error, Reason} ->
+ Fault =
+ io_lib:format("Attempt to change the file info to set the"
+ " preconditions of the test case failed ~p~n",
+ [Reason]),
+ {skip, Fault}
+ end.
+
+ticket_5913(doc) ->
+ ["Tests that a header without last-modified is handled"];
+ticket_5913(suite) -> [];
+ticket_5913(Config) ->
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
+ "GET /cgi-bin/erl/httpd_example:get_bin "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok.
+
+ticket_6003(doc) ->
+ ["Tests that a URI with a bad hexadecimal code is handled"];
+ticket_6003(suite) -> [];
+ticket_6003(Config) ->
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
+ "GET http://www.erlang.org/%skalle "
+ "HTTP/1.0\r\n\r\n",
+ [{statuscode, 400},
+ {version, "HTTP/1.0"}]),
+ ok.
+
+ticket_7304(doc) ->
+ ["Tests missing CR in delimiter"];
+ticket_7304(suite) ->
+ [];
+ticket_7304(Config) ->
+ ok = httpd_test_lib:verify_request(ip_comm, ?config(host, Config),
+ ?IP_PORT, ?config(node, Config),
+ "GET / HTTP/1.0\r\n\n",
+ [{statuscode, 200},
+ {version, "HTTP/1.0"}]),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+dos_hostname(Type, Port, Host, Node, Max) ->
+ H1 = {"", 200},
+ H2 = {"dummy-host.ericsson.se", 200},
+ TooLongHeader = lists:append(lists:duplicate(Max + 1, "a")),
+ H3 = {TooLongHeader, 403},
+ Hosts = [H1,H2,H3],
+ dos_hostname_poll(Type, Host, Port, Node, Hosts).
+
+%% make_ipv6(T) when is_tuple(T) andalso (size(T) =:= 8) ->
+%% make_ipv6(tuple_to_list(T));
+
+%% make_ipv6([_, _, _, _, _, _, _, _] = IPV6) ->
+%% lists:flatten(io_lib:format("~s:~s:~s:~s:~s:~s:~s:~s", IPV6)).
+
+
+%%--------------------------------------------------------------------
+%% Other help functions
+create_config(Config, Access, FileName) ->
+ ServerRoot = ?config(server_root, Config),
+ TcTopDir = ?config(tc_top_dir, Config),
+ Port = ?config(port, Config),
+ Type = ?config(sock_type, Config),
+ Host = ?config(host, Config),
+ Mods = io_lib:format("~p", [httpd_mod]),
+ Funcs = io_lib:format("~p", [ssl_password_cb]),
+ MaxHdrSz = io_lib:format("~p", [256]),
+ MaxHdrAct = io_lib:format("~p", [close]),
+
+ io:format(user,
+ "create_config -> "
+ "~n ServerRoot: ~p"
+ "~n TcTopDir: ~p"
+ "~n Type: ~p"
+ "~n Port: ~p"
+ "~n Host: ~p"
+ "~n", [ServerRoot, TcTopDir, Type, Port, Host]),
+
+ SSL =
+ if
+ (Type =:= ssl) orelse
+ (Type =:= essl) ->
+ [cline(["SSLCertificateFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLCertificateKeyFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLCACertificateFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLPasswordCallbackModule ", Mods]),
+ cline(["SSLPasswordCallbackFunction ", Funcs]),
+ cline(["SSLVerifyClient 0"]),
+ cline(["SSLVerifyDepth 1"])];
+ true ->
+ []
+ end,
+ ModOrder =
+ case Access of
+ mod_htaccess ->
+ "Modules mod_alias mod_htaccess mod_auth "
+ "mod_security "
+ "mod_responsecontrol mod_trace mod_esi "
+ "mod_actions mod_cgi mod_include mod_dir "
+ "mod_range mod_get "
+ "mod_head mod_log mod_disk_log";
+ _ ->
+ "Modules mod_alias mod_auth mod_security "
+ "mod_responsecontrol mod_trace mod_esi "
+ "mod_actions mod_cgi mod_include mod_dir "
+ "mod_range mod_get "
+ "mod_head mod_log mod_disk_log"
+ end,
+
+ %% The test suite currently does not handle an explicit BindAddress.
+ %% They assume any has been used, that is Addr is always set to undefined!
+
+ %% {ok, Hostname} = inet:gethostname(),
+ %% {ok, Addr} = inet:getaddr(Hostname, inet6),
+ %% AddrStr = make_ipv6(Addr),
+ %% BindAddress = lists:flatten(io_lib:format("~s|inet6", [AddrStr])),
+
+ BindAddress = "*|inet",
+ %% BindAddress = "*",
+
+ HttpConfig = [
+ cline(["Port ", integer_to_list(Port)]),
+ cline(["ServerName ", Host]),
+ cline(["SocketType ", atom_to_list(Type)]),
+ cline([ModOrder]),
+ %% cline(["LogFormat ", "erlang"]),
+ cline(["ServerAdmin [email protected]"]),
+ cline(["BindAddress ", BindAddress]),
+ cline(["ServerRoot ", ServerRoot]),
+ cline(["ErrorLog ", TcTopDir,
+ "/logs/error_log_", integer_to_list(Port)]),
+ cline(["TransferLog ", TcTopDir,
+ "/logs/access_log_", integer_to_list(Port)]),
+ cline(["SecurityLog ", TcTopDir,
+ "/logs/security_log_", integer_to_list(Port)]),
+ cline(["ErrorDiskLog ", TcTopDir,
+ "/logs/error_disk_log_", integer_to_list(Port)]),
+ cline(["ErrorDiskLogSize ", "190000 ", "11"]),
+ cline(["TransferDiskLog ", TcTopDir,
+ "/logs/access_disk_log_", integer_to_list(Port)]),
+ cline(["TransferDiskLogSize ", "200000 ", "10"]),
+ cline(["SecurityDiskLog ", TcTopDir,
+ "/logs/security_disk_log_", integer_to_list(Port)]),
+ cline(["SecurityDiskLogSize ", "210000 ", "9"]),
+ cline(["MaxClients 10"]),
+ cline(["MaxHeaderSize ", MaxHdrSz]),
+ cline(["MaxHeaderAction ", MaxHdrAct]),
+ cline(["DocumentRoot ",
+ filename:join(ServerRoot, "htdocs")]),
+ cline(["DirectoryIndex ", "index.html ", "welcome.html"]),
+ cline(["DefaultType ", "text/plain"]),
+ SSL,
+ mod_alias_config(ServerRoot),
+
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "open"]),
+ "Open Area",
+ filename:join(ServerRoot, "auth/passwd"),
+ filename:join(ServerRoot, "auth/group"),
+ plain,
+ "user one Aladdin",
+ filename:join(ServerRoot, "security_data")),
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "secret"]),
+ "Secret Area",
+ filename:join(ServerRoot, "auth/passwd"),
+ filename:join(ServerRoot, "auth/group"),
+ plain,
+ "group group1 group2",
+ filename:join(ServerRoot, "security_data")),
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "secret",
+ "top_secret"]),
+ "Top Secret Area",
+ filename:join(ServerRoot, "auth/passwd"),
+ filename:join(ServerRoot, "auth/group"),
+ plain,
+ "group group3",
+ filename:join(ServerRoot, "security_data")),
+
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "dets_open"]),
+ "Dets Open Area",
+ filename:join(ServerRoot, "passwd"),
+ filename:join(ServerRoot, "group"),
+ dets,
+ "user one Aladdin",
+ filename:join(ServerRoot, "security_data")),
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "dets_secret"]),
+ "Dets Secret Area",
+ filename:join(ServerRoot, "passwd"),
+ filename:join(ServerRoot, "group"),
+ dets,
+ "group group1 group2",
+ filename:join(ServerRoot, "security_data")),
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "dets_secret",
+ "top_secret"]),
+ "Dets Top Secret Area",
+ filename:join(ServerRoot, "passwd"),
+ filename:join(ServerRoot, "group"),
+ dets,
+ "group group3",
+ filename:join(ServerRoot, "security_data")),
+
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "mnesia_open"]),
+ "Mnesia Open Area",
+ false,
+ false,
+ mnesia,
+ "user one Aladdin",
+ filename:join(ServerRoot, "security_data")),
+ config_directory(filename:join([ServerRoot,"htdocs",
+ "mnesia_secret"]),
+ "Mnesia Secret Area",
+ false,
+ false,
+ mnesia,
+ "group group1 group2",
+ filename:join(ServerRoot, "security_data")),
+ config_directory(filename:join(
+ [ServerRoot, "htdocs", "mnesia_secret",
+ "top_secret"]),
+ "Mnesia Top Secret Area",
+ false,
+ false,
+ mnesia,
+ "group group3",
+ filename:join(ServerRoot, "security_data"))
+ ],
+ ConfigFile = filename:join([TcTopDir, FileName]),
+ {ok, Fd} = file:open(ConfigFile, [write]),
+ ok = file:write(Fd, lists:flatten(HttpConfig)),
+ ok = file:close(Fd).
+
+config_directory(Dir, AuthName, AuthUserFile, AuthGroupFile, AuthDBType,
+ Require, SF) ->
+ file:delete(SF),
+ [
+ cline(["<Directory ", Dir, ">"]),
+ cline(["SecurityDataFile ", SF]),
+ cline(["SecurityMaxRetries 3"]),
+ cline(["SecurityFailExpireTime ", integer_to_list(?FAIL_EXPIRE_TIME)]),
+ cline(["SecurityBlockTime 1"]),
+ cline(["SecurityAuthTimeout ", integer_to_list(?AUTH_TIMEOUT)]),
+ cline(["SecurityCallbackModule ", "httpd_mod"]),
+ cline_if_set("AuthUserFile", AuthUserFile),
+ cline_if_set("AuthGroupFile", AuthGroupFile),
+ cline_if_set("AuthName", AuthName),
+ cline_if_set("AuthDBType", AuthDBType),
+ cline(["require ", Require]),
+ cline(["</Directory>\r\n"])
+ ].
+
+mod_alias_config(Root) ->
+ [
+ cline(["Alias /icons/ ", filename:join(Root,"icons"), "/"]),
+ cline(["Alias /pics/ ", filename:join(Root, "icons"), "/"]),
+ cline(["ScriptAlias /cgi-bin/ ", filename:join(Root, "cgi-bin"), "/"]),
+ cline(["ScriptAlias /htbin/ ", filename:join(Root, "cgi-bin"), "/"]),
+ cline(["ErlScriptAlias /cgi-bin/erl httpd_example io"]),
+ cline(["EvalScriptAlias /eval httpd_example io"])
+ ].
+
+cline(List) ->
+ lists:flatten([List, "\r\n"]).
+
+cline_if_set(_, false) ->
+ [];
+cline_if_set(Name, Var) when is_list(Var) ->
+ cline([Name, " ", Var]);
+cline_if_set(Name, Var) when is_atom(Var) ->
+ cline([Name, " ", atom_to_list(Var)]).
+
+getaddr() ->
+ {ok,HostName} = inet:gethostname(),
+ {ok,{A1,A2,A3,A4}} = inet:getaddr(HostName,inet),
+ lists:flatten(io_lib:format("~p.~p.~p.~p",[A1,A2,A3,A4])).
+
+start_mnesia(Node) ->
+ case rpc:call(Node, ?MODULE, cleanup_mnesia, []) of
+ ok ->
+ ok;
+ Other ->
+ tsf({failed_to_cleanup_mnesia, Other})
+ end,
+ case rpc:call(Node, ?MODULE, setup_mnesia, []) of
+ {atomic, ok} ->
+ ok;
+ Other2 ->
+ tsf({failed_to_setup_mnesia, Other2})
+ end,
+ ok.
+
+setup_mnesia() ->
+ setup_mnesia([node()]).
+
+setup_mnesia(Nodes) ->
+ ok = mnesia:create_schema(Nodes),
+ ok = mnesia:start(),
+ {atomic, ok} = mnesia:create_table(httpd_user,
+ [{attributes,
+ record_info(fields, httpd_user)},
+ {disc_copies,Nodes}, {type, set}]),
+ {atomic, ok} = mnesia:create_table(httpd_group,
+ [{attributes,
+ record_info(fields,
+ httpd_group)},
+ {disc_copies,Nodes}, {type,bag}]).
+
+cleanup_mnesia() ->
+ mnesia:start(),
+ mnesia:delete_table(httpd_user),
+ mnesia:delete_table(httpd_group),
+ stopped = mnesia:stop(),
+ mnesia:delete_schema([node()]),
+ ok.
+
+create_htaccess_data(Path, IpAddress)->
+ create_htaccess_dirs(Path),
+
+ create_html_file(filename:join([Path,"ht/open/dummy.html"])),
+ create_html_file(filename:join([Path,"ht/blocknet/dummy.html"])),
+ create_html_file(filename:join([Path,"ht/secret/dummy.html"])),
+ create_html_file(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
+
+ create_htaccess_file(filename:join([Path,"ht/open/.htaccess"]),
+ Path, "user one Aladdin"),
+ create_htaccess_file(filename:join([Path,"ht/secret/.htaccess"]),
+ Path, "group group1 group2"),
+ create_htaccess_file(filename:join([Path,
+ "ht/secret/top_secret/.htaccess"]),
+ Path, "user four"),
+ create_htaccess_file(filename:join([Path,"ht/blocknet/.htaccess"]),
+ Path, nouser, IpAddress),
+
+ create_user_group_file(filename:join([Path,"ht","users.file"]),
+ "one:OnePassword\ntwo:TwoPassword\nthree:"
+ "ThreePassword\nfour:FourPassword\nAladdin:"
+ "AladdinPassword"),
+ create_user_group_file(filename:join([Path,"ht","groups.file"]),
+ "group1: two one\ngroup2: two three").
+
+create_html_file(PathAndFileName)->
+ file:write_file(PathAndFileName,list_to_binary(
+ "<html><head><title>test</title></head>
+ <body>testar</body></html>")).
+
+create_htaccess_file(PathAndFileName, BaseDir, RequireData)->
+ file:write_file(PathAndFileName,
+ list_to_binary(
+ "AuthUserFile "++ BaseDir ++
+ "/ht/users.file\nAuthGroupFile "++ BaseDir
+ ++ "/ht/groups.file\nAuthName Test\nAuthType"
+ " Basic\n<Limit>\nrequire " ++ RequireData ++
+ "\n</Limit>")).
+
+create_htaccess_file(PathAndFileName, BaseDir, nouser, IpAddress)->
+ file:write_file(PathAndFileName,list_to_binary(
+ "AuthUserFile "++ BaseDir ++
+ "/ht/users.file\nAuthGroupFile " ++
+ BaseDir ++ "/ht/groups.file\nAuthName"
+ " Test\nAuthType"
+ " Basic\n<Limit GET>\n\tallow from " ++
+ format_ip(IpAddress,
+ string:rchr(IpAddress,$.)) ++
+ "\n</Limit>")).
+
+create_user_group_file(PathAndFileName, Data)->
+ file:write_file(PathAndFileName, list_to_binary(Data)).
+
+create_htaccess_dirs(Path)->
+ ok = file:make_dir(filename:join([Path,"ht"])),
+ ok = file:make_dir(filename:join([Path,"ht/open"])),
+ ok = file:make_dir(filename:join([Path,"ht/blocknet"])),
+ ok = file:make_dir(filename:join([Path,"ht/secret"])),
+ ok = file:make_dir(filename:join([Path,"ht/secret/top_secret"])).
+
+remove_htaccess_dirs(Path)->
+ file:del_dir(filename:join([Path,"ht/secret/top_secret"])),
+ file:del_dir(filename:join([Path,"ht/secret"])),
+ file:del_dir(filename:join([Path,"ht/blocknet"])),
+ file:del_dir(filename:join([Path,"ht/open"])),
+ file:del_dir(filename:join([Path,"ht"])).
+
+format_ip(IpAddress,Pos)when Pos > 0->
+ case lists:nth(Pos,IpAddress) of
+ $.->
+ case lists:nth(Pos-2,IpAddress) of
+ $.->
+ format_ip(IpAddress,Pos-3);
+ _->
+ lists:sublist(IpAddress,Pos-2) ++ "."
+ end;
+ _ ->
+ format_ip(IpAddress,Pos-1)
+ end;
+
+format_ip(IpAddress, _Pos)->
+ "1" ++ IpAddress.
+
+remove_htaccess(Path)->
+ file:delete(filename:join([Path,"ht/open/dummy.html"])),
+ file:delete(filename:join([Path,"ht/secret/dummy.html"])),
+ file:delete(filename:join([Path,"ht/secret/top_secret/dummy.html"])),
+ file:delete(filename:join([Path,"ht/blocknet/dummy.html"])),
+ file:delete(filename:join([Path,"ht/blocknet/.htaccess"])),
+ file:delete(filename:join([Path,"ht/open/.htaccess"])),
+ file:delete(filename:join([Path,"ht/secret/.htaccess"])),
+ file:delete(filename:join([Path,"ht/secret/top_secret/.htaccess"])),
+ file:delete(filename:join([Path,"ht","users.file"])),
+ file:delete(filename:join([Path,"ht","groups.file"])),
+ remove_htaccess_dirs(Path).
+
+
+dos_hostname_poll(Type, Host, Port, Node, Hosts) ->
+ [dos_hostname_poll1(Type, Host, Port, Node, Host1, Code)
+ || {Host1,Code} <- Hosts].
+
+dos_hostname_poll1(Type, Host, Port, Node, Host1, Code) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ dos_hostname_request(Host1),
+ [{statuscode, Code},
+ {version, "HTTP/1.0"}]).
+
+dos_hostname_request(Host) ->
+ "GET / HTTP/1.0\r\n" ++ Host ++ "\r\n\r\n".
+
+get_nof_clients(Mode, Load) ->
+ get_nof_clients(test_server:os_type(), Mode, Load).
+
+get_nof_clients(_, ip_comm, light) -> 5;
+get_nof_clients(_, ssl, light) -> 2;
+get_nof_clients(_, ip_comm, medium) -> 10;
+get_nof_clients(_, ssl, medium) -> 4;
+get_nof_clients(_, ip_comm, heavy) -> 20;
+get_nof_clients(_, ssl, heavy) -> 6.
+
+%% Make a file 100 bytes long containing 012...9*10
+create_range_data(Path) ->
+ PathAndFileName=filename:join([Path,"range.txt"]),
+ file:write_file(PathAndFileName,list_to_binary(["12345678901234567890",
+ "12345678901234567890",
+ "12345678901234567890",
+ "12345678901234567890",
+ "12345678901234567890"])).
+
+create_ipv6_config(Config, FileName, Ipv6Address) ->
+ ServerRoot = ?config(server_root, Config),
+ TcTopDir = ?config(tc_top_dir, Config),
+ Port = ?config(port, Config),
+ SockType = ?config(sock_type, Config),
+ Mods = io_lib:format("~p", [httpd_mod]),
+ Funcs = io_lib:format("~p", [ssl_password_cb]),
+ Host = ?config(ipv6_host, Config),
+
+ MaxHdrSz = io_lib:format("~p", [256]),
+ MaxHdrAct = io_lib:format("~p", [close]),
+
+ Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
+ " mod_include mod_dir mod_get mod_head"
+ " mod_log mod_disk_log mod_trace",
+
+ SSL =
+ if
+ (SockType =:= ssl) orelse
+ (SockType =:= essl) ->
+ [cline(["SSLCertificateFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLCertificateKeyFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLCACertificateFile ",
+ filename:join(ServerRoot, "ssl/ssl_server.pem")]),
+ cline(["SSLPasswordCallbackModule ", Mods]),
+ cline(["SSLPasswordCallbackFunction ", Funcs]),
+ cline(["SSLVerifyClient 0"]),
+ cline(["SSLVerifyDepth 1"])];
+ true ->
+ []
+ end,
+
+ BindAddress = "[" ++ Ipv6Address ++"]|inet6",
+
+ HttpConfig =
+ [cline(["BindAddress ", BindAddress]),
+ cline(["Port ", integer_to_list(Port)]),
+ cline(["ServerName ", Host]),
+ cline(["SocketType ", atom_to_list(SockType)]),
+ cline([Mod_order]),
+ cline(["ServerRoot ", ServerRoot]),
+ cline(["DocumentRoot ", filename:join(ServerRoot, "htdocs")]),
+ cline(["MaxHeaderSize ",MaxHdrSz]),
+ cline(["MaxHeaderAction ",MaxHdrAct]),
+ cline(["DirectoryIndex ", "index.html "]),
+ cline(["DefaultType ", "text/plain"]),
+ SSL],
+ ConfigFile = filename:join([TcTopDir,FileName]),
+ {ok, Fd} = file:open(ConfigFile, [write]),
+ ok = file:write(Fd, lists:flatten(HttpConfig)),
+ ok = file:close(Fd).
+
+
+tsp(F) ->
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
+tsp(F, A) ->
+ inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
+
+tsf(Reason) ->
+ inets_test_lib:tsf(Reason).
diff --git a/lib/inets/test/old_httpd_SUITE_data/Makefile.src b/lib/inets/test/old_httpd_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..b0fdb43d8d
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/Makefile.src
@@ -0,0 +1,14 @@
+CC = @CC@
+LD = @LD@
+CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
+CROSSLDFLAGS = @CROSSLDFLAGS@
+
+PROGS = cgi_echo@exe@
+
+all: $(PROGS)
+
+cgi_echo@exe@: cgi_echo@obj@
+ $(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@
+
+cgi_echo@obj@: cgi_echo.c
+ $(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c
diff --git a/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c b/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c
new file mode 100644
index 0000000000..4670c02c56
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c
@@ -0,0 +1,97 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined __WIN32__
+#include <windows.h>
+#include <fcntl.h>
+#endif
+
+static int read_exact(char *buffer, int len);
+static int write_exact(char *buffer, int len);
+
+int main(void)
+{
+ char msg[100];
+ int msg_len;
+#ifdef __WIN32__
+ _setmode(_fileno( stdin), _O_BINARY);
+ _setmode(_fileno( stdout), _O_BINARY);
+#endif
+ msg_len = read_exact(msg, 100);
+
+ write_exact("Content-type: text/plain\r\n\r\n", 28);
+ write_exact(msg, msg_len);
+ exit(EXIT_SUCCESS);
+}
+
+
+/* read from stdin */
+#ifdef __WIN32__
+static int read_exact(char *buffer, int len)
+{
+ HANDLE standard_input = GetStdHandle(STD_INPUT_HANDLE);
+
+ unsigned read_result;
+ unsigned sofar = 0;
+
+ if (!len) { /* Happens for "empty packages */
+ return 0;
+ }
+ for (;;) {
+ if (!ReadFile(standard_input, buffer + sofar,
+ len - sofar, &read_result, NULL)) {
+ return -1; /* EOF */
+ }
+ if (!read_result) {
+ return -2; /* Interrupted while reading? */
+ }
+ sofar += read_result;
+ if (sofar == len) {
+ return len;
+ }
+ }
+}
+#else
+static int read_exact(char *buffer, int len) {
+ int i, got = 0;
+
+ do {
+ if ((i = read(0, buffer + got, len - got)) <= 0)
+ return(i);
+ got += i;
+ } while (got < len);
+ return len;
+
+}
+#endif
+
+/* write to stdout */
+#ifdef __WIN32__
+ static int write_exact(char *buffer, int len)
+ {
+ HANDLE standard_output = GetStdHandle(STD_OUTPUT_HANDLE);
+ unsigned written;
+
+ if (!WriteFile(standard_output, buffer, len, &written, NULL)) {
+ return -1; /* Broken Pipe */
+ }
+ if (written < ((unsigned) len)) {
+ /* This should not happen, standard output is not blocking? */
+ return -2;
+ }
+
+ return (int) written;
+}
+
+#else
+ static int write_exact(char *buffer, int len) {
+ int i, wrote = 0;
+
+ do {
+ if ((i = write(1, buffer + wrote, len - wrote)) <= 0)
+ return i;
+ wrote += i;
+ } while (wrote < len);
+ return len;
+ }
+#endif
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/Makefile b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
index d7a3231068..489f3cfb7a 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/Makefile
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2010. All Rights Reserved.
+# Copyright Ericsson AB 1997-2014. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -34,22 +34,22 @@ RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
# ----------------------------------------------------
# Target Specs
# ----------------------------------------------------
-MODULE=
+MODULE=
AUTH_FILES = auth/group \
- auth/passwd
-CGI_FILES = cgi-bin/printenv.sh
+ auth/passwd
+CGI_FILES = cgi-bin/printenv.sh
CONF_FILES = conf/8080.conf \
conf/8888.conf \
conf/httpd.conf \
conf/ssl.conf \
- conf/mime.types
-OPEN_FILES = htdocs/open/dummy.html
-MNESIA_OPEN_FILES = htdocs/mnesia_open/dummy.html
+ conf/mime.types
+OPEN_FILES = htdocs/open/dummy.html
+MNESIA_OPEN_FILES = htdocs/mnesia_open/dummy.html
MISC_FILES = htdocs/misc/friedrich.html \
htdocs/misc/oech.html
-SECRET_FILES = htdocs/secret/dummy.html
-MNESIA_SECRET_FILES = htdocs/mnesia_secret/dummy.html
+SECRET_FILES = htdocs/secret/dummy.html
+MNESIA_SECRET_FILES = htdocs/mnesia_secret/dummy.html
HTDOCS_FILES = htdocs/index.html \
htdocs/config.shtml \
htdocs/echo.shtml \
@@ -162,7 +162,7 @@ ERL_COMPILE_FLAGS +=
# Targets
# ----------------------------------------------------
-debug opt:
+debug opt:
clean:
@@ -170,7 +170,7 @@ docs:
# ----------------------------------------------------
# Release Target
-# ----------------------------------------------------
+# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
@@ -206,4 +206,3 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/logs
release_docs_spec:
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group
new file mode 100644
index 0000000000..b3da0ccbd3
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group
@@ -0,0 +1,3 @@
+group1: one two
+group2: two three
+group3: three Aladdin
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd
new file mode 100644
index 0000000000..8c980ff547
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd
@@ -0,0 +1,4 @@
+one:onePassword
+two:twoPassword
+three:threePassword
+Aladdin:AladdinPassword
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat
new file mode 100644
index 0000000000..c6b1704819
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat
@@ -0,0 +1,7 @@
+@echo off
+echo tomrad > c:\cygwin\tmp\hej
+echo Content-type: text/html
+echo.
+echo ^<HTML^> ^<HEAD^> ^<TITLE^>OS Environment^</TITLE^> ^</HEAD^> ^<BODY^>^<PRE^>
+set
+echo ^</PRE^>^</BODY^>^</HTML^>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh
new file mode 100755
index 0000000000..de81de9bde
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo "Content-type: text/html"
+echo ""
+echo "<HTML> <HEAD> <TITLE>OS Environment</TITLE> </HEAD> <BODY><PRE>"
+env
+echo "</PRE></BODY></HTML>" \ No newline at end of file
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/8080.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
index 48e66f0114..48e66f0114 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/conf/8080.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/8888.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
index 79bb7fcca4..79bb7fcca4 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/conf/8888.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/httpd.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
index ceb94237d2..a1de5bf4a8 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/conf/httpd.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
@@ -1,19 +1,19 @@
#
# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2011. All Rights Reserved.
-#
+#
+# Copyright Ericsson AB 1997-2014. All Rights Reserved.
+#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
# compliance with the License. You should have received a copy of the
# Erlang Public License along with this software. If not, it can be
# retrieved online at http://www.erlang.org/.
-#
+#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
-#
+#
# %CopyrightEnd%
#
#
@@ -26,17 +26,17 @@ Port 8888
# BindAddress: This directive is used to tell the server which IP address
# to listen to. It can either contain "*", an IP address, or a fully
# qualified Internet domain name.
-#
+#
# It is also possible to specify the ip-family with the directive.
# There ar three possible value: inet, inet6 and inet6fb4
# inet: Use IpFamily inet when retreiving the address and
# fail if that does not work.
# inet6: Use IpFamily inet6 when retreiving the address and
# fail if that does not work.
-# inet6fb4: First IpFamily inet6 is tried and if that does not work,
-# inet is used as fallback.
+# inet6fb4: First IpFamily inet6 is tried and if that does not work,
+# inet is used as fallback.
# Default value for ip-family is inet6fb4
-#
+#
# The syntax is: <address>[|<ip-family>]
#
#BindAddress *
@@ -47,7 +47,7 @@ Port 8888
# your server if it's different than the one the program would get (i.e. use
# "www" instead of the host's real name).
#
-# Note: You cannot just invent host names and hope they work. The name you
+# Note: You cannot just invent host names and hope they work. The name you
# define here must be a valid DNS name for your host. If you don't understand
# this, ask your network administrator.
@@ -158,7 +158,7 @@ DirectoryIndex index.html welcome.html
DefaultType text/plain
-# Aliases: Add here as many aliases as you need (with no limit). The format is
+# Aliases: Add here as many aliases as you need (with no limit). The format is
# Alias fakename realname
Alias /icons/ /var/tmp/server_root/icons/
@@ -215,7 +215,7 @@ SSLVerifyClient 0
# Each directory to which INETS has access, can be configured with respect
# to which services and features are allowed and/or disabled in that
-# directory (and its subdirectories).
+# directory (and its subdirectories).
<Directory /var/tmp/server_root/htdocs/open>
AuthDBType plain
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/mime.types b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types
index d2f81e4e5e..cb23079659 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/conf/mime.types
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types
@@ -460,6 +460,3 @@ video/vnd.vivo
video/x-msvideo avi
video/x-sgi-movie movie
x-conference/x-cooltalk ice
-
-
-
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/conf/ssl.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
index 8b8c57a98b..8b8c57a98b 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/conf/ssl.conf
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml
new file mode 100644
index 0000000000..4bfddf4ed5
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml
@@ -0,0 +1,60 @@
+<HTML>
+<HEAD>
+<TITLE>/ssi.html (17-Apr-1997)</TITLE>
+</HEAD>
+<BODY>
+<H1>/ssi.html</H1>
+
+<!-- ************* CONFIG ************* -->
+
+<!--#config timefmt="%a %b %e %T %Z %Y" sizefmt="abbrev"-->
+<!--#config errmsg="[an especially ugly error occurred while processing this directive]"-->
+
+<!-- ************* INCLUDE ************* -->
+
+<P>Include /misc/friedrich.html:
+<!--#include virtual="/misc/friedrich.html"-->
+<P>Include /misc/not_defined.html: <!--#include virtual="/misc/not_defined.html"-->
+<P>Include misc/friedrich.html:
+<!--#include file="misc/friedrich.html"-->
+<P>Include not_defined.html: <!--#include file="not_defined.html"-->
+
+<P><HR>
+
+<!-- ************* ECHO ************* -->
+
+<P>DOCUMENT_NAME: <!--#echo var="DOCUMENT_NAME"-->
+<P>DOCUMENT_URI: <!--#echo var="DOCUMENT_URI"-->
+<P>QUERY_STRING_UNESCAPED: <!--#echo var="QUERY_STRING_UNESCAPED"-->
+<P>DATE_LOCAL: <!--#echo var="DATE_LOCAL"-->
+<P>DATE_GMT: <!--#echo var="DATE_GMT"-->
+<P>LAST_MODIFIED: <!--#echo var="LAST_MODIFIED"-->
+<P>NOT_DEFINED: <!--#echo var="NOT_DEFINED"-->
+
+<P><HR>
+
+<!-- ************* FSIZE ************* -->
+
+<P>Size of index.html: <!--#fsize file="index.html"-->
+<P>Size of not_defined.html: <!--#fsize file="not_defined.html"-->
+<!--#config sizefmt="bytes"-->
+<P>Size of /misc/friedrich.html: <!--#fsize virtual="/misc/friedrich.html"-->
+<P>Size of /misc/not_defined.html: <!--#fsize virtual="/misc/not_defined.html"-->
+
+<P><HR>
+
+<!-- ************* FLASTMOD ************* -->
+
+<P>Last modification of index.html: <!--#flastmod file="index.html"-->
+<P>Last modification of not_defined.html: <!--#flastmod file="not_defined.html"-->
+<P>Last modification of /misc/friedrich.html: <!--#flastmod virtual="/misc/friedrich.html"-->
+<P>Last modification of /misc/not_defined.html: <!--#flastmod virtual="/misc/not_defined.html"-->
+
+<!--#exec cmd="ls"-->
+<!--#exec cmd="printenv"-->
+<!--#exec cmd="sunemaja"-->
+
+<!--#exec cgi="/cgi-bin/printenv.sh"-->
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html
new file mode 100644
index 0000000000..a6e8a35a04
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html
@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>/open/dummy.html (17-Apr-1997)</TITLE>
+<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
+<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
+</HEAD>
+<BODY>
+<H1>/open/dummy.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html
new file mode 100644
index 0000000000..016b04e540
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html
@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE>
+<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
+<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
+</HEAD>
+<BODY>
+<H1>/secret/dummy.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html
new file mode 100644
index 0000000000..34db3d5d1a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html
@@ -0,0 +1,9 @@
+<HTML>
+<HEAD>
+<TITLE>/secret/top_secret/index.html (04-Feb-1998)</TITLE>
+<!-- Created by: Mattias Nilsson, 04-Feb-1998 -->
+</HEAD>
+<BODY>
+<H1>/secret/top_secret/index.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml
new file mode 100644
index 0000000000..168ae1c05a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml
@@ -0,0 +1,25 @@
+<HTML>
+<HEAD>
+<TITLE>/echo.shtml</TITLE>
+</HEAD>
+<BODY>
+<H1>/echo.shtml</H1>
+
+<P>DOCUMENT_NAME: <!--#echo var="DOCUMENT_NAME"-->
+
+<P>DOCUMENT_URI: <!--#echo var="DOCUMENT_URI"-->
+
+<P>QUERY_STRING_UNESCAPED: <!--#echo var="QUERY_STRING_UNESCAPED"-->
+
+<P>DATE_LOCAL: <!--#echo var="DATE_LOCAL"-->
+
+<P>DATE_GMT: <!--#echo var="DATE_GMT"-->
+
+<P>LAST_MODIFIED: <!--#echo var="LAST_MODIFIED"-->
+
+<P>NOT_DEFINED: <!--#echo var="NOT_DEFINED"-->
+
+<P>[<A HREF="ssi.html">Back</A>]
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml
new file mode 100644
index 0000000000..b4cb3a7815
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml
@@ -0,0 +1,20 @@
+<HTML>
+<HEAD>
+<TITLE>/exec.shtml</TITLE>
+</HEAD>
+<BODY>
+<H1>/exec.shtml</H1>
+<PRE>
+<!--#exec cmd="ls"-->
+<HR>
+<!--#exec cmd="printenv"-->
+<HR>
+<!--#exec cmd="sunemaja"-->
+<HR>
+<!--#exec cgi="/cgi-bin/printenv.sh"-->
+</PRE>
+
+<P>[<A HREF="ssi.html">Back</A>]
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml
new file mode 100644
index 0000000000..9b02de1338
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml
@@ -0,0 +1,19 @@
+<HTML>
+<HEAD>
+<TITLE>/flastmod.shtml</TITLE>
+</HEAD>
+<BODY>
+<H1>/flastmod.shtml</H1>
+
+<P>Last modification of index.html: <!--#flastmod file="index.html"-->
+
+<P>Last modification of not_defined.html: <!--#flastmod file="not_defined.html"-->
+
+<P>Last modification of /misc/friedrich.html: <!--#flastmod virtual="/misc/friedrich.html"-->
+
+<P>Last modification of /misc/not_defined.html: <!--#flastmod virtual="/misc/not_defined.html"-->
+
+<P>[<A HREF="ssi.html">Back</A>]
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml
new file mode 100644
index 0000000000..aed7384898
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml
@@ -0,0 +1,19 @@
+<HTML>
+<HEAD>
+<TITLE>/fsize.shtml</TITLE>
+</HEAD>
+<BODY>
+<H1>/fsize.shtml</H1>
+
+<P>Size of index.html: <!--#fsize file="index.html"-->
+
+<P>Size of not_defined.html: <!--#fsize file="not_defined.html"-->
+
+<P>Size of /misc/friedrich.html: <!--#fsize virtual="/misc/friedrich.html"-->
+
+<P>Size of /misc/not_defined.html: <!--#fsize virtual="/misc/not_defined.html"-->
+
+<P>[<A HREF="ssi.html">Back</A>]
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml
new file mode 100644
index 0000000000..71fcc4bce9
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml
@@ -0,0 +1,23 @@
+<HTML>
+<HEAD>
+<TITLE>/include.shtml</TITLE>
+</HEAD>
+<BODY>
+<H1>/include.shtml</H1>
+
+<P>Include /misc/friedrich.html:
+<!--#include virtual="/misc/friedrich.html"-->
+
+<P>Include /misc/not_defined.html:
+<!--#include virtual="/misc/not_defined.html"-->
+
+<P>Include misc/friedrich.html:
+<!--#include file="misc/friedrich.html"-->
+
+<P>Include not_defined.html:
+<!--#include file="not_defined.html"-->
+
+<P>[<A HREF="ssi.html">Back</A>]
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html
new file mode 100644
index 0000000000..cfdc9f9ab7
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html
@@ -0,0 +1,25 @@
+<HTML>
+<HEAD>
+<TITLE>/index.html</TITLE>
+</HEAD>
+<BODY>
+<H1>/index.html</H1>
+
+<STRONG>Server-Side Include (SSI) commands:</STRONG><BR>
+<A HREF="config.shtml">config</A><BR>
+<A HREF="echo.shtml">echo</A><BR>
+<A HREF="exec.shtml">exec</A><BR>
+<A HREF="flastmod.shtml">flastmod</A><BR>
+<A HREF="fsize.shtml">fsize</A><BR>
+<A HREF="include.shtml">include</A><BR>
+
+<BR>
+<BR>
+
+<STRONG>ESI callback:</STRING><BR>
+<A HREF="cgi-bin/erl/httpd_example/get">cgi-bin/erl/httpd_example/get</A><BR>
+<A HREF="cgi-bin/erl/httpd_example/yahoo">cgi-bin/erl/httpd_example/yahoo</A><BR>
+<A HREF="cgi-bin/erl/httpd_example/test1">cgi-bin/erl/httpd_example/test1</A><BR>
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html
new file mode 100644
index 0000000000..02c0e698b5
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html
@@ -0,0 +1,12 @@
+<HTML>
+<HEAD>
+<TITLE>/last_modified.html</TITLE>
+</HEAD>
+<BODY>
+<H1>/last_modified.html</H1>
+
+<P>This document is only used for test of illegal last-modified date.</P>
+
+
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html
new file mode 100644
index 0000000000..d7953d5df4
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html
@@ -0,0 +1,7 @@
+<P><CITE>
+Talking much about oneself can also be a means to conceal oneself.<BR>
+-- Friedrich Nietzsche
+</CITE>
+
+<P>Nested Include:
+<!--#include file="misc/oech.html"-->
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html
new file mode 100644
index 0000000000..506064bf04
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html
@@ -0,0 +1,4 @@
+<P><CITE>
+What excuses stand in your way? How can you eliminate them?<BR>
+-- Roger von Oech
+</CITE>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html
new file mode 100644
index 0000000000..8c17451f91
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html
@@ -0,0 +1 @@
+<HTML></HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html
new file mode 100644
index 0000000000..a6e8a35a04
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html
@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>/open/dummy.html (17-Apr-1997)</TITLE>
+<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
+<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
+</HEAD>
+<BODY>
+<H1>/open/dummy.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html
new file mode 100644
index 0000000000..016b04e540
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html
@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE>
+<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
+<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
+</HEAD>
+<BODY>
+<H1>/secret/dummy.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html
new file mode 100644
index 0000000000..2d17e8b596
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html
@@ -0,0 +1,9 @@
+<HTML>
+<HEAD>
+<TITLE>/mnesia_secret/top_secret/index.html (04-Feb-1998)</TITLE>
+<!-- Created by: Mattias Nilsson, 04-Feb-1998 -->
+</HEAD>
+<BODY>
+<H1>/mnesia_secret/top_secret/index.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html
new file mode 100644
index 0000000000..a6e8a35a04
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html
@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>/open/dummy.html (17-Apr-1997)</TITLE>
+<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
+<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
+</HEAD>
+<BODY>
+<H1>/open/dummy.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html
new file mode 100644
index 0000000000..016b04e540
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html
@@ -0,0 +1,10 @@
+<HTML>
+<HEAD>
+<TITLE>/secret/dummy.html (17-Apr-1997)</TITLE>
+<!-- Created by: Joakim Greben�, 17-Apr-1997 -->
+<!-- Changed by: Joakim Greben�, 17-Apr-1997 -->
+</HEAD>
+<BODY>
+<H1>/secret/dummy.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html
new file mode 100644
index 0000000000..34db3d5d1a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html
@@ -0,0 +1,9 @@
+<HTML>
+<HEAD>
+<TITLE>/secret/top_secret/index.html (04-Feb-1998)</TITLE>
+<!-- Created by: Mattias Nilsson, 04-Feb-1998 -->
+</HEAD>
+<BODY>
+<H1>/secret/top_secret/index.html</H1>
+</BODY>
+</HTML>
diff --git a/lib/inets/test/httpd_SUITE_data/server_root/icons/README b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README
index a1fc5a5a9c..a1fc5a5a9c 100644
--- a/lib/inets/test/httpd_SUITE_data/server_root/icons/README
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif
new file mode 100644
index 0000000000..bb23d971f4
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif
new file mode 100644
index 0000000000..eaecd2172a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif
new file mode 100644
index 0000000000..a423894043
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif
new file mode 100644
index 0000000000..3a1c139fc4
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif
new file mode 100644
index 0000000000..a694ae1ec3
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif
new file mode 100644
index 0000000000..eb84268c4c
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif
new file mode 100644
index 0000000000..a8425cb574
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif
new file mode 100644
index 0000000000..9a15cbae04
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif
new file mode 100644
index 0000000000..62d0363108
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif
new file mode 100644
index 0000000000..0ccf01e198
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif
new file mode 100644
index 0000000000..270fdb1c06
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif
new file mode 100644
index 0000000000..65dcd002ea
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif
new file mode 100644
index 0000000000..c43bc4faec
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif
new file mode 100644
index 0000000000..9f8cbe9f76
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif
new file mode 100644
index 0000000000..fbdcf575f7
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif
new file mode 100644
index 0000000000..eb97cb7333
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif
new file mode 100644
index 0000000000..fe0c97998c
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif
new file mode 100644
index 0000000000..7698455bf9
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif
new file mode 100644
index 0000000000..a8b8319232
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif
new file mode 100644
index 0000000000..0fd15a0d7f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif
new file mode 100644
index 0000000000..64241e5c5d
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif
new file mode 100644
index 0000000000..867cfd1212
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif
new file mode 100644
index 0000000000..b3f5fb248f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif
new file mode 100644
index 0000000000..7a308be8f6
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif
new file mode 100644
index 0000000000..9acba576c0
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif
new file mode 100644
index 0000000000..3883088e7a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif
new file mode 100644
index 0000000000..c4dc3887db
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif
new file mode 100644
index 0000000000..7555b6c164
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif
new file mode 100644
index 0000000000..f8d76a8c23
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif
new file mode 100644
index 0000000000..7664cd0364
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif
new file mode 100644
index 0000000000..39e732739f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif
new file mode 100644
index 0000000000..b0ffb7e0cc
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif
new file mode 100644
index 0000000000..48264601ae
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif
new file mode 100644
index 0000000000..a354c871cd
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif
new file mode 100644
index 0000000000..791be33105
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif
new file mode 100644
index 0000000000..fbe353c282
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif
new file mode 100644
index 0000000000..48264601ae
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif
new file mode 100644
index 0000000000..30979cb528
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif
new file mode 100644
index 0000000000..75332d9e59
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif
new file mode 100644
index 0000000000..b2959b4c85
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif
new file mode 100644
index 0000000000..de60b2940f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif
new file mode 100644
index 0000000000..94743981d9
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif
new file mode 100644
index 0000000000..88d5240c3c
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif
new file mode 100644
index 0000000000..5cdbc7206d
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif
new file mode 100644
index 0000000000..85a5d68317
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif
new file mode 100644
index 0000000000..35443fb63a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif
new file mode 100644
index 0000000000..ad1686e448
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif
new file mode 100644
index 0000000000..01e442bfa9
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif
new file mode 100644
index 0000000000..751faeea36
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif
new file mode 100644
index 0000000000..4f30484ff6
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif
new file mode 100644
index 0000000000..162478fb3a
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif
new file mode 100644
index 0000000000..c96338a152
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif
new file mode 100644
index 0000000000..279e6710d4
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif
new file mode 100644
index 0000000000..c5b6889a76
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif
new file mode 100644
index 0000000000..0035183774
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif
new file mode 100644
index 0000000000..7b917b4e91
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif
new file mode 100644
index 0000000000..39bc90e795
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif
new file mode 100644
index 0000000000..c88fd777c4
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif
new file mode 100644
index 0000000000..6f7a0ae7a7
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif
new file mode 100644
index 0000000000..03aa6be71e
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif
new file mode 100644
index 0000000000..b04c5e0908
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif
new file mode 100644
index 0000000000..4db9d023ed
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif
new file mode 100644
index 0000000000..93471fdd88
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif
new file mode 100644
index 0000000000..57aee93f07
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif
new file mode 100644
index 0000000000..0dc327b569
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif
new file mode 100644
index 0000000000..8661337f06
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif
new file mode 100644
index 0000000000..59ddb34ce0
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif
new file mode 100644
index 0000000000..0e6e506e00
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif
new file mode 100644
index 0000000000..d324ab80ea
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif
new file mode 100644
index 0000000000..0f565bc1db
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif
new file mode 100644
index 0000000000..818a5cdc7e
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif
new file mode 100644
index 0000000000..b256e5f75f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif
new file mode 100644
index 0000000000..af6ba2b097
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif
new file mode 100644
index 0000000000..06dccb3e44
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif
new file mode 100644
index 0000000000..d8a853bc58
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif
new file mode 100644
index 0000000000..8efb49f55d
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif
new file mode 100644
index 0000000000..48e6a7fb2f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif
new file mode 100644
index 0000000000..7067070da2
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif
new file mode 100644
index 0000000000..a9e462a377
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif
new file mode 100644
index 0000000000..4cfe0a5e0f
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif
new file mode 100644
index 0000000000..a0c83cb85b
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif
new file mode 100644
index 0000000000..617e779efa
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif
new file mode 100644
index 0000000000..45e43233b8
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif
new file mode 100644
index 0000000000..4c623909fb
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif
new file mode 100644
index 0000000000..33697dbb66
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif
new file mode 100644
index 0000000000..32b1ea23fb
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif
new file mode 100644
index 0000000000..6d6d6d1ebf
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif
new file mode 100644
index 0000000000..4387d529f6
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif
new file mode 100644
index 0000000000..4387d529f6
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif
new file mode 100644
index 0000000000..05b4ec2058
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif
new file mode 100644
index 0000000000..e3203f7a88
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif
Binary files differ
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip b/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem
new file mode 100644
index 0000000000..427447958d
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem
@@ -0,0 +1,31 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSVwC+n
+0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53h2Zr
+3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwIDAQAB
+AoGACdIVYe/LTeydUihtInC8lZ2QuPgJmoBNocRjqJFipEihoL4scHAx25n1bBvB
+I0HZphffzBkGp28oBAtl2LRPWXqu527unc/RWRfLMqSK1xNSq1DxD1a30zkrZPna
+QiV65vEJuNSJTtlDy/Zqc/BVZXCpxWlzYQedZgkmf0Qse8ECQQCmaz02Yur8zC9f
+eSQKU5OSzGw3bSIumEzziCfHdTheK6MEoccf5TCAyLXhZwA7QlKja4tFXfeyVxws
+/LlnUJN9AkEA4j+xnOeYUyGKXL5i+BAbnqpI4MzPiq+IoCYkaRlD/wAws24r5HNI
+ZQmEHWqD/NNzOf/A2XuyLtMiTGJPW/DftwJBAKKpJP6Ytuh6xz8BUCnLwO12Y7vV
+LtjuQiCzD3aUa5EYA9HOMqxJPxxRkf0LyR0i2VUkE8+sZiPpov+R0cJa7p0CQQCj
+40GUiArGRSiF7/+e84QeVfl+pb29F1QftiFv5DZmFEwy3Z572KpbTh5edJbxYHY6
+UDHxGHJFCvnwXNJhpkVXAkBJqfEfiMJ3Q/E5Gpf3sQizacouW92iiN8ojlF1oB80
+t34RysJH7SgI3gdMhTribCo2UUaV0StjR6yodPN+TB2J
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIChzCCAfCgAwIBAgIGAIsapa8BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
+BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
+BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
+VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
+MDAwWjB7MQ8wDQYDVQQDEwZjbGllbnQxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
+cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
+VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCTFBPkOO98fDY3j6MIxIGKp+rampfIay50Lx4+EnCnRSSV
+wC+n0VVmP7V5SGFJpuXJzN0hvqPUWOOjiMTNlNRaGy0pqu2oMXWAPLOxHWL1wT53
+h2Zr3FUNU/N0Rvnkttse1KZJ9uYCLKUiuXXsv2rR62nH3OhRIiBHSAcSv0NRWwID
+AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAG8t6f1A
+PF7xayGxtUpG2r6W5ETylC3ZIKPS2kfJk9aYi7AZNTp7/xTU6SgqvFBN8aBPzxCD
+4jHrSNC8DSb4X1x9uimarb6qdZDHEdij+DRAd2eygJHZxEf7+8B4Fx34thQeU9hZ
+S1Izke5AlsyFMkvB7h0anE4k9BfuU70vl6v5
+-----END CERTIFICATE-----
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem
new file mode 100644
index 0000000000..4aac86db49
--- /dev/null
+++ b/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem
@@ -0,0 +1,31 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9Adq6
+7k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ4UAt
+NHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQIDAQAB
+AoGAQIlma0r6W6bcRj4+Wd4fXCFvHuq5Psu1fYEeC5Yvz8761xVjjSfbrDHJZ9pm
+FjOEgedK+s5lbDXqYVyjbdyZSugStBRocSmbG8SQHcAsxR2ZIkNzX2hYzB+lslWo
+T3YJojDyB134O7XJznCu+ZFXP86jyJ1JT6k6a+OIHcwnJ+ECQQDYn57dY4Px3mEd
+VBLStN3YkRF5oFyT+xk7IaKeLLB6n4gCnoVbBoHut7PFbPYPzoNzEwPk3MQKDIHb
+Kig3S5CpAkEAvPA1VmoJWAlN6kUi+F2L8HXEArzE8x7vwdsslrwMKUe4dFS+ZC/7
+5iDOaxcZ7TYkCgwzBt341++DCgP6j3fY1QJBALB6AcOcwi52m6l4B8mu3ZkEPjdX
+BHTuONTqhv/TqoaLlxODL2NDvvDKqeMp7KBd/srt79swW2lQXS4+fvrlTdkCQQCm
+zxj4O1QWkthkfje6ubSkTwUIOatUzrp1F9GNH2dJRtX2dx9FCwxGCC7WY6XzRXqa
+GF0wsedSllbGD+82nWQlAkAicMGqCqRq4hKR/cVmFatOqKVWCVkx6OFF2FhuiI5Z
+h5eIOPGCt8dVRs1P9DNSld/D98Sfm65m85z8BtXovvYV
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIChzCCAfCgAwIBAgIGANUxXM9BMA0GCSqGSIb3DQEBBQUAMHoxDjAMBgNVBAMT
+BW90cENBMSAwHgYJKoZIhvcNAQkBFhF0ZXN0ZXJAZXJsYW5nLm9yZzESMBAGA1UE
+BxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTEPMA0GA1UEChMGZXJsYW5nMRQwEgYD
+VQQLEwt0ZXN0aW5nIGRlcDAiGA8yMDEwMDkwMTAwMDAwMFoYDzIwMjUwODI4MDAw
+MDAwWjB7MQ8wDQYDVQQDEwZzZXJ2ZXIxIDAeBgkqhkiG9w0BCQEWEXRlc3RlckBl
+cmxhbmcub3JnMRIwEAYDVQQHEwlTdG9ja2hvbG0xCzAJBgNVBAYTAlNFMQ8wDQYD
+VQQKEwZlcmxhbmcxFDASBgNVBAsTC3Rlc3RpbmcgZGVwMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCf4Htxr99lLs5W8QQw7jdakqyAkIjOW4aqH8sr4va4SvZ9
+Adq67k8jMHefCVZo+F8x4cwsBgB4aWzFIGBnvFTi6YsH27XW7f9O9IPCej8fdhRZ
+4UAtNHa253buOWpDGla2JmIdkmfFvXFJycMIKbG5tYilVXoWKBMKmCwWaXz0nQID
+AQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAGF5Pfwk
+QDdwJup/mVITPxbBls4Yl7anDooUQsq8066lA1g54H/PRfXscGkyCFGh1ifXvf1L
+psMRoBAdDHL/wSJplk3rRavkC94eBgnTFZmfKL6844g1j53yameiYL8IEVExYMBg
+/XGyc0qwq57WT8B/K4aElrvlBlQ0wF3wN54M
+-----END CERTIFICATE-----
diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl
new file mode 100644
index 0000000000..9ba09e1474
--- /dev/null
+++ b/lib/inets/test/uri_SUITE.erl
@@ -0,0 +1,159 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+%%
+%% ct:run("../inets_test", uri_SUITE).
+%%
+
+-module(uri_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include("inets_test_lib.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-define(GOOGLE, "www.google.com").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+suite() ->
+ [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ ipv4,
+ ipv6,
+ host,
+ userinfo,
+ scheme,
+ queries,
+ escaped,
+ hexed_query
+ ].
+
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ Config.
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+
+init_per_testcase(_Case, Config) ->
+ Config.
+end_per_testcase(_Case, _Config) ->
+ ok.
+
+%%-------------------------------------------------------------------------
+%% Test cases starts here.
+%%-------------------------------------------------------------------------
+
+ipv4(Config) when is_list(Config) ->
+ {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
+ http_uri:parse("http://127.0.0.1/foobar.html").
+
+ipv6(Config) when is_list(Config) ->
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
+ {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, true}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{ipv6_host_with_brackets, false}]),
+ {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
+ http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
+ [{foo, false}]),
+ {error,
+ {malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
+ http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html").
+
+host(Config) when is_list(Config) ->
+ {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
+ http_uri:parse("http://localhost:8888/foobar.html").
+
+userinfo(Config) when is_list(Config) ->
+ {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
+ http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html").
+
+scheme(Config) when is_list(Config) ->
+ {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
+ {error, {malformed_url, _, _}} =
+ http_uri:parse("localhost:8888/foobar.html").
+
+queries(Config) when is_list(Config) ->
+ {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
+ http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42").
+
+escaped(Config) when is_list(Config) ->
+ {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
+ http_uri:parse("http://www.somedomain.com/%2Eabc"),
+ {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
+ http_uri:parse("http://www.somedomain.com/%252Eabc"),
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
+ http_uri:parse("http://www.somedomain.com/%25abc"),
+ {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
+ http_uri:parse("http://www.somedomain.com/%25abc?foo=bar").
+
+hexed_query(doc) ->
+ [{doc, "Solves OTP-6191"}];
+hexed_query(Config) when is_list(Config) ->
+ Google = ?GOOGLE,
+ GoogleSearch = "http://" ++ Google ++ "/search",
+ Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
+ URI1 = GoogleSearch ++ Search1,
+ Search2 = "?hl=en&q=%25%25",
+ URI2 = GoogleSearch ++ Search2,
+ Search3 = "?hl=en&q=%foo",
+ URI3 = GoogleSearch ++ Search3,
+
+ Verify1 =
+ fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
+ (_) -> error
+ end,
+ Verify2 = Verify1,
+ Verify3 = Verify1,
+ verify_uri(URI1, Verify1),
+ verify_uri(URI2, Verify2),
+ verify_uri(URI3, Verify3).
+
+
+%%--------------------------------------------------------------------
+%% Internal Functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+
+verify_uri(URI, Verify) ->
+ case http_uri:parse(URI) of
+ {ok, ParsedURI} ->
+ case Verify(ParsedURI) of
+ ok ->
+ ok;
+ error ->
+ Reason = {unexpected_parse_result, URI, ParsedURI},
+ ERROR = {error, Reason},
+ throw(ERROR)
+ end;
+ {error, _} = ERROR ->
+ throw(ERROR)
+ end.