aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/doc/src/notes.xml25
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/notes.xml27
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/compile.xml9
-rw-r--r--lib/compiler/doc/src/notes.xml16
-rw-r--r--lib/compiler/src/beam_a.erl3
-rw-r--r--lib/compiler/src/beam_block.erl92
-rw-r--r--lib/compiler/src/beam_bs.erl3
-rw-r--r--lib/compiler/src/beam_bsm.erl3
-rw-r--r--lib/compiler/src/beam_dead.erl23
-rw-r--r--lib/compiler/src/beam_disasm.erl93
-rw-r--r--lib/compiler/src/beam_disasm.hrl3
-rw-r--r--lib/compiler/src/beam_except.erl3
-rw-r--r--lib/compiler/src/beam_peep.erl3
-rw-r--r--lib/compiler/src/beam_receive.erl3
-rw-r--r--lib/compiler/src/beam_record.erl129
-rw-r--r--lib/compiler/src/beam_reorder.erl3
-rw-r--r--lib/compiler/src/beam_type.erl19
-rw-r--r--lib/compiler/src/beam_utils.erl318
-rw-r--r--lib/compiler/src/beam_validator.erl5
-rw-r--r--lib/compiler/src/beam_z.erl3
-rw-r--r--lib/compiler/src/compile.erl25
-rw-r--r--lib/compiler/src/core_lint.erl6
-rwxr-xr-xlib/compiler/src/genop.tab9
-rw-r--r--lib/compiler/src/sys_core_alias.erl3
-rw-r--r--lib/compiler/src/sys_core_bsm.erl3
-rw-r--r--lib/compiler/src/sys_core_dsetel.erl3
-rw-r--r--lib/compiler/src/sys_core_fold.erl15
-rw-r--r--lib/compiler/src/v3_codegen.erl331
-rw-r--r--lib/compiler/src/v3_core.erl28
-rw-r--r--lib/compiler/src/v3_kernel.erl20
-rw-r--r--lib/compiler/src/v3_kernel.hrl2
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl31
-rw-r--r--lib/compiler/test/beam_utils_SUITE.erl66
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl4
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl6
-rw-r--r--lib/compiler/test/compile_SUITE.erl25
-rw-r--r--lib/compiler/test/guard_SUITE.erl4
-rw-r--r--lib/compiler/test/map_SUITE.erl20
-rw-r--r--lib/compiler/test/match_SUITE.erl74
-rw-r--r--lib/compiler/test/misc_SUITE.erl3
-rw-r--r--lib/compiler/test/receive_SUITE.erl13
-rw-r--r--lib/compiler/test/trycatch_SUITE.erl124
-rw-r--r--lib/compiler/test/z_SUITE.erl3
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/cosEvent/doc/src/notes.xml17
-rw-r--r--lib/cosEvent/vsn.mk2
-rw-r--r--lib/cosEventDomain/doc/src/notes.xml17
-rw-r--r--lib/cosEventDomain/vsn.mk2
-rw-r--r--lib/cosFileTransfer/doc/src/notes.xml17
-rw-r--r--lib/cosFileTransfer/vsn.mk2
-rw-r--r--lib/cosNotification/doc/src/notes.xml17
-rw-r--r--lib/cosNotification/vsn.mk2
-rw-r--r--lib/cosProperty/doc/src/notes.xml17
-rw-r--r--lib/cosProperty/vsn.mk2
-rw-r--r--lib/cosTime/doc/src/notes.xml17
-rw-r--r--lib/cosTime/vsn.mk2
-rw-r--r--lib/cosTransactions/doc/src/notes.xml17
-rw-r--r--lib/cosTransactions/vsn.mk2
-rw-r--r--lib/crypto/doc/src/notes.xml70
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/notes.xml15
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/notes.xml23
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl1
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl1
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/doc/src/notes.xml16
-rw-r--r--lib/diameter/doc/src/seealso.ent2
-rw-r--r--lib/diameter/src/diameter.appup.src6
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/edoc/doc/src/notes.xml15
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/eldap/doc/src/notes.xml15
-rw-r--r--lib/eldap/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml21
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/doc/src/notes.xml15
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/eunit/doc/src/notes.xml15
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/hipe/doc/src/notes.xml33
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl5
-rw-r--r--lib/hipe/icode/hipe_icode_primops.erl6
-rw-r--r--lib/hipe/icode/hipe_icode_range.erl3
-rw-r--r--lib/hipe/main/hipe.app.src2
-rw-r--r--lib/hipe/rtl/hipe_rtl_binary_construct.erl10
-rw-r--r--lib/hipe/rtl/hipe_rtl_primops.erl2
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/ic/doc/src/notes.xml17
-rw-r--r--lib/ic/vsn.mk2
-rw-r--r--lib/inets/doc/src/notes.xml32
-rw-r--r--lib/inets/test/Makefile11
-rw-r--r--lib/inets/test/http_test_lib.erl180
-rw-r--r--lib/inets/test/httpc_SUITE.erl17
-rw-r--r--lib/inets/test/httpd_bench_SUITE.erl846
-rw-r--r--lib/inets/test/httpd_bench_SUITE_data/1M_filebin0 -> 1000000 bytes
-rw-r--r--lib/inets/test/httpd_bench_SUITE_data/1k_filebin0 -> 1000 bytes
-rw-r--r--lib/inets/test/httpd_block.erl372
-rw-r--r--lib/inets/test/httpd_test_lib.erl73
-rw-r--r--lib/inets/test/inets.spec4
-rw-r--r--lib/inets/test/inets_bench.spec1
-rw-r--r--lib/inets/test/inets_test_lib.erl38
-rw-r--r--lib/inets/test/make_certs.erl530
-rw-r--r--lib/inets/test/old_httpd_SUITE.erl2347
-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/Makefile210
-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.bat9
-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.conf79
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf63
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf269
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types465
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf66
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml70
-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.shtml35
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml30
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml29
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml29
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml33
-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.html22
-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/README161
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gifbin247 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gifbin2326 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gifbin216 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gifbin233 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gifbin205 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gifbin148 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gifbin308 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gifbin268 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gifbin247 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gifbin235 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gifbin755 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gifbin781 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gifbin785 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gifbin745 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gifbin786 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gifbin780 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gifbin791 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gifbin796 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gifbin784 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gifbin784 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gifbin587 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gifbin576 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gifbin246 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gifbin1038 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gifbin214 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gifbin225 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gifbin163 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gifbin238 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gifbin236 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gifbin225 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gifbin243 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gifbin219 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gifbin221 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gifbin220 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gifbin249 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gifbin217 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gifbin223 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gifbin1822 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gifbin11977 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gifbin274 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gifbin309 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gifbin286 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gifbin268 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gifbin276 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gifbin172 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gifbin249 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gifbin243 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gifbin237 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gifbin249 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gifbin188 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gifbin198 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gifbin198 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gifbin191 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gifbin193 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gifbin189 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gifbin186 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gifbin185 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gifbin173 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gifbin254 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gifbin2748 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gifbin244 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gifbin267 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gifbin172 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gifbin258 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gifbin263 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gifbin248 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gifbin221 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gifbin285 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gifbin264 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gifbin89 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gifbin53 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gifbin243 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gifbin251 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gifbin229 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gifbin242 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gifbin245 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gifbin164 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gifbin236 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gifbin236 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gifbin228 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gifbin261 -> 0 bytes
-rw-r--r--lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip1
-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/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/notes.xml15
-rw-r--r--lib/jinterface/java_src/pom.xml.src11
-rw-r--r--lib/jinterface/vsn.mk2
-rw-r--r--lib/kernel/doc/src/net_kernel.xml2
-rw-r--r--lib/kernel/doc/src/notes.xml15
-rw-r--r--lib/kernel/src/Makefile1
-rw-r--r--lib/kernel/src/file_io_server.erl21
-rw-r--r--lib/kernel/src/kernel.app.src2
-rw-r--r--lib/kernel/src/kernel.erl11
-rw-r--r--lib/kernel/src/kernel_refc.erl139
-rw-r--r--lib/kernel/test/kernel_SUITE.erl69
-rw-r--r--lib/kernel/test/prim_file_SUITE.erl15
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/doc/src/notes.xml17
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/notes.xml44
-rw-r--r--lib/mnesia/src/mnesia_checkpoint.erl4
-rw-r--r--lib/mnesia/src/mnesia_schema.erl16
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/notes.xml67
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/doc/src/notes.xml17
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/orber/doc/src/notes.xml23
-rw-r--r--lib/orber/vsn.mk2
-rw-r--r--lib/os_mon/doc/src/notes.xml15
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/otp_mibs/doc/src/notes.xml15
-rw-r--r--lib/otp_mibs/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/notes.xml15
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/public_key/doc/src/notes.xml25
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/runtime_tools/doc/src/notes.xml15
-rw-r--r--lib/runtime_tools/src/observer_backend.erl6
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/notes.xml20
-rw-r--r--lib/sasl/test/release_handler_SUITE.erl38
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/doc/src/notes.xml17
-rw-r--r--lib/snmp/vsn.mk2
-rw-r--r--lib/ssh/doc/src/notes.xml59
-rw-r--r--lib/ssh/src/ssh.app.src4
-rw-r--r--lib/ssh/src/ssh_auth.erl9
-rw-r--r--lib/ssh/src/ssh_dbg.erl38
-rw-r--r--lib/ssh/src/ssh_transport.erl18
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl10
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl2
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl5
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl6
-rw-r--r--lib/ssh/test/ssh_test_lib.erl29
-rw-r--r--lib/ssh/test/ssh_test_lib.hrl5
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl3
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/notes.xml55
-rw-r--r--lib/ssl/doc/src/ssl_introduction.xml2
-rw-r--r--lib/ssl/doc/src/using_ssl.xml37
-rw-r--r--lib/ssl/src/dtls_connection.erl36
-rw-r--r--lib/ssl/src/dtls_handshake.erl7
-rw-r--r--lib/ssl/src/dtls_udp_listener.erl7
-rw-r--r--lib/ssl/src/ssl.app.src2
-rw-r--r--lib/ssl/src/ssl_handshake.erl8
-rw-r--r--lib/ssl/src/tls_connection.erl9
-rw-r--r--lib/ssl/src/tls_handshake.erl9
-rw-r--r--lib/ssl/test/ssl.spec6
-rw-r--r--lib/ssl/vsn.mk2
-rw-r--r--lib/stdlib/doc/src/digraph.xml4
-rw-r--r--lib/stdlib/doc/src/notes.xml43
-rw-r--r--lib/stdlib/src/base64.erl597
-rw-r--r--lib/stdlib/src/erl_compile.erl3
-rw-r--r--lib/stdlib/src/erl_lint.erl44
-rw-r--r--lib/stdlib/src/erl_parse.yrl82
-rw-r--r--lib/stdlib/src/gen.erl4
-rw-r--r--lib/stdlib/test/base64_SUITE.erl109
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl39
-rw-r--r--lib/stdlib/test/rand_SUITE.erl208
-rw-r--r--lib/stdlib/test/stdlib.spec3
-rw-r--r--lib/stdlib/test/stdlib_bench.spec2
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE.erl326
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl31
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl31
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl31
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl33
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl33
-rw-r--r--lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl35
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/notes.xml15
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl14
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl44
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/tools/doc/src/notes.xml15
-rw-r--r--lib/tools/emacs/erlang.el2
-rw-r--r--lib/tools/src/cover.erl18
-rw-r--r--lib/tools/test/cover_SUITE.erl28
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/wx/doc/src/notes.xml16
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--lib/xmerl/doc/src/notes.xml15
-rw-r--r--lib/xmerl/vsn.mk2
333 files changed, 5709 insertions, 5568 deletions
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index ae6660c143..1abe983221 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -32,6 +32,31 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 5.0.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ There was a issue with BER encoding and the
+ <c>undec_rest</c> option in generated decoders. An
+ exception could be thrown instead of returning an error
+ tuple.</p>
+ <p>
+ Own Id: OTP-14786 Aux Id: ERL-518 </p>
+ </item>
+ <item>
+ <p>
+ The asn1ct:test functions crashed on decoders generated
+ with options <c>no_ok_wrapper</c>, <c>undec_rest</c>.</p>
+ <p>
+ Own Id: OTP-14787 Aux Id: ERL-518 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index ef83b9e3dc..4cd89089e9 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1 +1 @@
-ASN1_VSN = 5.0.3
+ASN1_VSN = 5.0.4
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index b039023e0f..c6b928bb5d 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -33,6 +33,33 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.15.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new function, <c>ct:remaining_test_procs/0</c>, returns
+ the identity of test- and group leader processes that are
+ still running at the time of the call.</p>
+ <p>
+ Own Id: OTP-13832</p>
+ </item>
+ <item>
+ <p>
+ A "latest test result" link is now displayed in the
+ footer of each test index page, which performs a jump to
+ the most recently generated test index. This is useful
+ for making quick comparisons of results between test runs
+ without having to traverse the log file tree.</p>
+ <p>
+ Own Id: OTP-14281</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.15.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 7b959ebfe3..96fdc89853 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.15.2
+COMMON_TEST_VSN = 1.15.3
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index b398871ddf..06afc55c07 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -233,6 +233,15 @@ module.beam: module.erl \
header.hrl</code>
</item>
+ <tag><c>makedep_side_effect</c></tag>
+ <item>
+ <p>The dependecies are created as a side effect to the
+ normal compilation process. This means that the object
+ file will also be produced. This option override the
+ <c>makedep</c> option.
+ </p>
+ </item>
+
<tag><c>{makedep_output, Output}</c></tag>
<item>
<p>Writes generated rules to <c>Output</c> instead of the
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 2aec75a2aa..f4a3f9875b 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The '<c>deterministic</c>' option was not recognized
+ when given in a <c>-compile()</c> attribute in the source
+ code.</p>
+ <p>
+ Own Id: OTP-14773 Aux Id: ERL-498 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.1.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
index cdb32d5d55..6f09dc4be4 100644
--- a/lib/compiler/src/beam_a.erl
+++ b/lib/compiler/src/beam_a.erl
@@ -42,8 +42,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = beam_jump:remove_unused_labels(Is1),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index c640af224d..fe1ce6f60b 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -37,16 +37,16 @@ function({function,Name,Arity,CLabel,Is0}) ->
%% Collect basic blocks and optimize them.
Is1 = blockify(Is0),
Is2 = embed_lines(Is1),
- Is3 = move_allocates(Is2),
- Is4 = beam_utils:live_opt(Is3),
- Is5 = opt_blocks(Is4),
- Is6 = beam_utils:delete_live_annos(Is5),
-
- %% Done.
- {function,Name,Arity,CLabel,Is6}
+ Is3 = beam_utils:anno_defs(Is2),
+ Is4 = move_allocates(Is3),
+ Is5 = beam_utils:live_opt(Is4),
+ Is6 = opt_blocks(Is5),
+ Is = beam_utils:delete_live_annos(Is6),
+
+ %% Done.
+ {function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -173,7 +173,7 @@ find_fixpoint(OptFun, Is0) ->
%% safe to assume that if x(N) is initialized, then all lower-numbered
%% x registers are also initialized.
%%
-%% For example, in general it is not safe to transform the following
+%% For example, we must be careful when transforming the following
%% instructions:
%%
%% get_tuple_element x(0) Element => x(1)
@@ -185,13 +185,9 @@ find_fixpoint(OptFun, Is0) ->
%% get_tuple_element x(0) Element => x(1)
%%
%% The transformation is safe if and only if x(1) has been
-%% initialized previously. Unfortunately, beam_reorder may have moved
-%% a get_tuple_element instruction so that x(1) is not always
-%% initialized when this code is reached. To find whether or not x(1)
-%% is initialized, we would need to analyze all code preceding these
-%% two instructions (across branches). Since we currently don't have
-%% any practical mechanism for doing that, we will have to
-%% conservatively assume that the transformation is unsafe.
+%% initialized previously. We will use the annotations added by
+%% beam_utils:anno_defs/1 to determine whether x(a) has been
+%% initialized.
move_allocates([{block,Bl0}|Is]) ->
Bl = move_allocates_1(reverse(Bl0), []),
@@ -200,15 +196,20 @@ move_allocates([I|Is]) ->
[I|move_allocates(Is)];
move_allocates([]) -> [].
+move_allocates_1([{'%def',_}|Is], Acc) ->
+ move_allocates_1(Is, Acc);
move_allocates_1([I|Is], [{set,[],[],{alloc,Live0,Info}}|Acc]=Acc0) ->
- case {alloc_may_pass(I),alloc_live_regs(I, Live0)} of
- {false,_} ->
- move_allocates_1(Is, [I|Acc0]);
- {true,not_possible} ->
- move_allocates_1(Is, [I|Acc0]);
- {true,Live} when is_integer(Live) ->
- A = {set,[],[],{alloc,Live,Info}},
- move_allocates_1(Is, [A,I|Acc])
+ case alloc_may_pass(I) of
+ false ->
+ move_allocates_1(Is, [I|Acc0]);
+ true ->
+ case alloc_live_regs(I, Is, Live0) of
+ not_possible ->
+ move_allocates_1(Is, [I|Acc0]);
+ Live when is_integer(Live) ->
+ A = {set,[],[],{alloc,Live,Info}},
+ move_allocates_1(Is, [A,I|Acc])
+ end
end;
move_allocates_1([I|Is], Acc) ->
move_allocates_1(Is, [I|Acc]);
@@ -472,16 +473,34 @@ count_ones(Bits, Acc) ->
%% Calculate the new number of live registers when we move an allocate
%% instruction upwards, passing a 'set' instruction.
-alloc_live_regs({set,Ds,Ss,_}, Regs0) ->
+alloc_live_regs({set,Ds,Ss,_}, Is, Regs0) ->
Rset = x_live(Ss, x_dead(Ds, (1 bsl Regs0)-1)),
- live_regs(0, Rset).
+ Live = live_regs(0, Rset),
+ case ensure_contiguous(Rset, Live) of
+ not_possible ->
+ %% Liveness information (looking forward in the
+ %% instruction stream) can't prove that moving this
+ %% allocation instruction is safe. Now use the annotation
+ %% of defined registers at the beginning of the current
+ %% block to see whether moving would be safe.
+ Def0 = defined_regs(Is, 0),
+ Def = Def0 band ((1 bsl Live) - 1),
+ ensure_contiguous(Rset bor Def, Live);
+ Live ->
+ %% Safe based on liveness information.
+ Live
+ end.
live_regs(N, 0) ->
N;
-live_regs(N, Regs) when Regs band 1 =:= 1 ->
- live_regs(N+1, Regs bsr 1);
-live_regs(_, _) ->
- not_possible.
+live_regs(N, Regs) ->
+ live_regs(N+1, Regs bsr 1).
+
+ensure_contiguous(Regs, Live) ->
+ case (1 bsl Live) - 1 of
+ Regs -> Live;
+ _ -> not_possible
+ end.
x_dead([{x,N}|Rs], Regs) -> x_dead(Rs, Regs band (bnot (1 bsl N)));
x_dead([_|Rs], Regs) -> x_dead(Rs, Regs);
@@ -490,3 +509,14 @@ x_dead([], Regs) -> Regs.
x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
x_live([_|Rs], Regs) -> x_live(Rs, Regs);
x_live([], Regs) -> Regs.
+
+%% defined_regs(ReversedInstructions) -> RegBitmap.
+%% Given a reversed instruction stream, determine the
+%% the registers that are defined.
+
+defined_regs([{'%def',Def}|_], Regs) ->
+ Def bor Regs;
+defined_regs([{set,Ds,_,{alloc,Live,_}}|_], Regs) ->
+ x_live(Ds, Regs bor ((1 bsl Live) - 1));
+defined_regs([{set,Ds,_,_}|Is], Regs) ->
+ defined_regs(Is, x_live(Ds, Regs)).
diff --git a/lib/compiler/src/beam_bs.erl b/lib/compiler/src/beam_bs.erl
index beb055b23d..14cedbb582 100644
--- a/lib/compiler/src/beam_bs.erl
+++ b/lib/compiler/src/beam_bs.erl
@@ -38,8 +38,7 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
{Is,Lc} = bsm_opt(Is1, Lc0),
{{function,Name,Arity,CLabel,Is},Lc}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 9a4e7fb133..9ea5a3eb92 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -105,8 +105,7 @@ function({function,Name,Arity,Entry,Is}, FIndex) ->
D = #btb{f=FIndex,index=Index},
{function,Name,Arity,Entry,btb_opt_1(Is, D, [])}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
index d379fdc4eb..da944f3ce6 100644
--- a/lib/compiler/src/beam_dead.erl
+++ b/lib/compiler/src/beam_dead.erl
@@ -56,8 +56,7 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
Is = move_move_into_block(Is3, []),
{{function,Name,Arity,CLabel,Is},Lc}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -272,7 +271,8 @@ backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) ->
end;
backward([{jump,{f,To}}=J|[{bif,Op,{f,BifFail},Ops,Reg}|Is]=Is0], D, Acc) ->
try replace_comp_op(To, Reg, Op, Ops, D) of
- I -> backward(Is, D, I++Acc)
+ {Test,Jump} ->
+ backward([Jump,Test|Is], D, Acc)
catch
throw:not_possible ->
case To =:= BifFail of
@@ -446,7 +446,7 @@ prune_redundant([], _) -> [].
replace_comp_op(To, Reg, Op, Ops, D) ->
False = comp_op_find_shortcut(To, Reg, {atom,false}, D),
True = comp_op_find_shortcut(To, Reg, {atom,true}, D),
- [bif_to_test(Op, Ops, False),{jump,{f,True}}].
+ {bif_to_test(Op, Ops, False),{jump,{f,True}}}.
comp_op_find_shortcut(To0, Reg, Val, D) ->
case shortcut_select_label(To0, Reg, Val, D) of
@@ -483,15 +483,22 @@ not_possible() -> throw(not_possible).
%% F1: is_eq_exact F2 Reg Lit2 F1: is_eq_exact F2 Reg Lit2
%% L2: .... L2:
%%
-combine_eqs(To, [Reg,{Type,_}=Lit1]=Ops, D, [{label,L1}|_])
- when Type =:= atom; Type =:= integer ->
+combine_eqs(To, [Reg,{Type,_}=Lit1]=Ops, D, Acc)
+ when Type =:= atom; Type =:= integer ->
+ Next = case Acc of
+ [{label,Lbl}|_] -> Lbl;
+ [{jump,{f,Lbl}}|_] -> Lbl
+ end,
case beam_utils:code_at(To, D) of
[{test,is_eq_exact,{f,F2},[Reg,{Type,_}=Lit2]},
{label,L2}|_] when Lit1 =/= Lit2 ->
- {select,select_val,Reg,{f,F2},[Lit1,{f,L1},Lit2,{f,L2}]};
+ {select,select_val,Reg,{f,F2},[Lit1,{f,Next},Lit2,{f,L2}]};
+ [{test,is_eq_exact,{f,F2},[Reg,{Type,_}=Lit2]},
+ {jump,{f,L2}}|_] when Lit1 =/= Lit2 ->
+ {select,select_val,Reg,{f,F2},[Lit1,{f,Next},Lit2,{f,L2}]};
[{select,select_val,Reg,{f,F2},[{Type,_}|_]=List0}|_] ->
List = remove_from_list(Lit1, List0),
- {select,select_val,Reg,{f,F2},[Lit1,{f,L1}|List]};
+ {select,select_val,Reg,{f,F2},[Lit1,{f,Next}|List]};
_Is ->
{test,is_eq_exact,{f,To},Ops}
end;
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 8fd0b36d05..22ba86fa38 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -163,8 +163,8 @@ pp_instr(I) ->
file(File) ->
try process_chunks(File)
- catch error:Reason ->
- {error,?MODULE,{internal,{Reason,erlang:get_stacktrace()}}}
+ catch error:Reason:Stack ->
+ {error,?MODULE,{internal,{Reason,Stack}}}
end.
%%-----------------------------------------------------------------------
@@ -719,42 +719,6 @@ resolve_inst({wait,[Lbl]},_,_,_) ->
{wait,Lbl};
resolve_inst({wait_timeout,[Lbl,Int]},_,_,_) ->
{wait_timeout,Lbl,resolve_arg(Int)};
-resolve_inst({m_plus,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'+',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_minus,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'-',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_times,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'*',W,[SrcR1,SrcR2],DstR};
-resolve_inst({m_div,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'/',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_div,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'div',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_rem,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'rem',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_band,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'band',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bor,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bor',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bxor,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bxor',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bsl,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bsl',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bsr,Args},_,_,_) ->
- [W,SrcR1,SrcR2,DstR] = resolve_args(Args),
- {arithbif,'bsr',W,[SrcR1,SrcR2],DstR};
-resolve_inst({int_bnot,Args},_,_,_) ->
- [W,SrcR,DstR] = resolve_args(Args),
- {arithbif,'bnot',W,[SrcR],DstR};
resolve_inst({is_lt=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
@@ -800,9 +764,6 @@ resolve_inst({is_nil=I,Args0},_,_,_) ->
resolve_inst({is_binary=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
-resolve_inst({is_constant=I,Args0},_,_,_) ->
- [L|Args] = resolve_args(Args0),
- {test,I,L,Args};
resolve_inst({is_list=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
@@ -840,11 +801,6 @@ resolve_inst({get_tuple_element,[Src,{u,Off},Dst]},_,_,_) ->
{get_tuple_element,resolve_arg(Src),Off,resolve_arg(Dst)};
resolve_inst({set_tuple_element,[Src,Dst,{u,Off}]},_,_,_) ->
{set_tuple_element,resolve_arg(Src),resolve_arg(Dst),Off};
-resolve_inst({put_string,[{u,Len},{u,Off},Dst]},_,Strings,_) ->
- String = if Len > 0 -> binary_to_list(Strings, Off+1, Off+Len);
- true -> ""
- end,
- {put_string,Len,{string,String},Dst};
resolve_inst({put_list,[Src1,Src2,Dst]},_,_,_) ->
{put_list,resolve_arg(Src1),resolve_arg(Src2),Dst};
resolve_inst({put_tuple,[{u,Arity},Dst]},_,_,_) ->
@@ -859,9 +815,6 @@ resolve_inst({case_end,[X]},_,_,_) ->
{case_end,resolve_arg(X)};
resolve_inst({call_fun,[{u,N}]},_,_,_) ->
{call_fun,N};
-resolve_inst({make_fun,Args},_,_,Lbls) ->
- [{f,L},Magic,FreeVars] = resolve_args(Args),
- {make_fun,lookup(L,Lbls),Magic,FreeVars};
resolve_inst({is_function=I,Args0},_,_,_) ->
[L|Args] = resolve_args(Args0),
{test,I,L,Args};
@@ -870,30 +823,6 @@ resolve_inst({call_ext_only,[{u,N},{u,MFAix}]},Imports,_,_) ->
%%
%% Instructions for handling binaries added in R7A & R7B
%%
-resolve_inst({bs_start_match,[F,Reg]},_,_,_) ->
- {bs_start_match,F,Reg};
-resolve_inst({bs_get_integer=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_get_float=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_get_binary=I,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
- [A2,A5] = resolve_args([Arg2,Arg5]),
- {test,I,Lbl,[A2,N,decode_field_flags(U),A5]};
-resolve_inst({bs_skip_bits,[Lbl,Arg2,{u,N},{u,U}]},_,_,_) ->
- A2 = resolve_arg(Arg2),
- {test,bs_skip_bits,Lbl,[A2,N,decode_field_flags(U)]};
-resolve_inst({bs_test_tail,[F,{u,N}]},_,_,_) ->
- {test,bs_test_tail,F,[N]};
-resolve_inst({bs_save,[{u,N}]},_,_,_) ->
- {bs_save,N};
-resolve_inst({bs_restore,[{u,N}]},_,_,_) ->
- {bs_restore,N};
-resolve_inst({bs_init,[{u,N},{u,U}]},_,_,_) ->
- {bs_init,N,decode_field_flags(U)};
-resolve_inst({bs_final,[F,X]},_,_,_) ->
- {bs_final,F,X};
resolve_inst({bs_put_integer,[Lbl,Arg2,{u,N},{u,U},Arg5]},_,_,_) ->
[A2,A5] = resolve_args([Arg2,Arg5]),
{bs_put_integer,Lbl,A2,N,decode_field_flags(U),A5};
@@ -908,8 +837,6 @@ resolve_inst({bs_put_string,[{u,Len},{u,Off}]},_,Strings,_) ->
true -> ""
end,
{bs_put_string,Len,{string,String}};
-resolve_inst({bs_need_buf,[{u,N}]},_,_,_) ->
- {bs_need_buf,N};
%%
%% Instructions for handling floating point numbers added in June 2001 (R8).
@@ -961,9 +888,6 @@ resolve_inst({raise,[_Reg1,_Reg2]=Regs},_,_,_) ->
resolve_inst({bs_init2,[Lbl,Arg2,{u,W},{u,R},{u,F},Arg6]},_,_,_) ->
[A2,A6] = resolve_args([Arg2,Arg6]),
{bs_init2,Lbl,A2,W,R,decode_field_flags(F),A6};
-resolve_inst({bs_bits_to_bytes,[Lbl,Arg2,Arg3]},_,_,_) ->
- [A2,A3] = resolve_args([Arg2,Arg3]),
- {bs_bits_to_bytes,Lbl,A2,A3};
resolve_inst({bs_add=I,[Lbl,Arg2,Arg3,Arg4,Arg5]},_,_,_) ->
[A2,A3,A4,A5] = resolve_args([Arg2,Arg3,Arg4,Arg5]),
{I,Lbl,[A2,A3,A4],A5};
@@ -1041,12 +965,6 @@ resolve_inst({gc_bif3,Args},Imports,_,_) ->
{gc_bif,BifName,F,Live,[A1,A2,A3],Reg};
%%
-%% New instructions for creating non-byte aligned binaries.
-%%
-resolve_inst({bs_final2,[X,Y]},_,_,_) ->
- {bs_final2,X,Y};
-
-%%
%% R11B-5.
%%
resolve_inst({is_bitstr=I,Args0},_,_,_) ->
@@ -1165,6 +1083,13 @@ resolve_inst({get_map_elements,Args0},_,_,_) ->
{get_map_elements,FLbl,Src,{list,List}};
%%
+%% OTP 21.
+%%
+
+resolve_inst({build_stacktrace,[]},_,_,_) ->
+ build_stacktrace;
+
+%%
%% Catches instructions that are not yet handled.
%%
resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
diff --git a/lib/compiler/src/beam_disasm.hrl b/lib/compiler/src/beam_disasm.hrl
index d968cd9587..8cc0bcf99b 100644
--- a/lib/compiler/src/beam_disasm.hrl
+++ b/lib/compiler/src/beam_disasm.hrl
@@ -26,7 +26,8 @@
%% IT SHOULD BE MOVED TO A FILE THAT DEFINES (AND EXPORTS)
%% PROPER TYPES FOR THE SET OF BEAM INSTRUCTIONS.
%%
--type beam_instr() :: 'bs_init_writable' | 'fclearerror' | 'if_end'
+-type beam_instr() :: 'bs_init_writable' | 'build_stacktrace'
+ | 'fclearerror' | 'if_end'
| 'remove_message' | 'return' | 'send' | 'timeout'
| tuple(). %% XXX: Very underspecified - FIX THIS
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
index 9801c68ee2..abd39c661d 100644
--- a/lib/compiler/src/beam_except.erl
+++ b/lib/compiler/src/beam_except.erl
@@ -45,8 +45,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = function_1(Is0),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl
index 9436c20b36..eb3192fe8f 100644
--- a/lib/compiler/src/beam_peep.erl
+++ b/lib/compiler/src/beam_peep.erl
@@ -41,8 +41,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = beam_jump:remove_unused_labels(Is1),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index 468460eedf..3c8efa577c 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.erl
@@ -82,8 +82,7 @@ function({function,Name,Arity,Entry,Is}) ->
D = beam_utils:index_labels(Is),
{function,Name,Arity,Entry,opt(Is, D, [])}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_record.erl b/lib/compiler/src/beam_record.erl
index 419089b1bc..db1053e48c 100644
--- a/lib/compiler/src/beam_record.erl
+++ b/lib/compiler/src/beam_record.erl
@@ -15,19 +15,12 @@
%%
%% %CopyrightEnd%
%%
-%% File: beam_record.erl
-%% Author: Björn-Egil Dahlberg
-%% Created: 2014-09-03
-%%
-
--module(beam_record).
--export([module/2]).
%% Rewrite the instruction stream on tagged tuple tests.
-%% Tagged tuples means a tuple of any arity with an atom as its first element.
-%% Typically records, ok-tuples and error-tuples.
-%%
-%% from:
+%% Tagged tuples means a tuple of any arity with an atom as its
+%% first element, such as records and error tuples.
+%%
+%% From:
%% ...
%% {test,is_tuple,Fail,[Src]}.
%% {test,test_arity,Fail,[Src,Sz]}.
@@ -36,13 +29,16 @@
%% ...
%% {test,is_eq_exact,Fail,[Dst,Atom]}.
%% ...
-%% to:
+%% To:
%% ...
%% {test,is_tagged_tuple,Fail,[Src,Sz,Atom]}.
%% ...
+%%
+-module(beam_record).
+-export([module/2]).
--import(lists, [reverse/1]).
+-import(lists, [reverse/1,reverse/2]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -51,56 +47,85 @@ module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
Fs = [function(F) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is}) ->
+function({function,Name,Arity,CLabel,Is0}) ->
try
- Idx = beam_utils:index_labels(Is),
- {function,Name,Arity,CLabel,rewrite(Is,Idx)}
+ Is1 = beam_utils:anno_defs(Is0),
+ Idx = beam_utils:index_labels(Is1),
+ Is = rewrite(reverse(Is1), Idx),
+ {function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
-rewrite(Is,Idx) ->
- rewrite(Is,Idx,[]).
+rewrite(Is, Idx) ->
+ rewrite(Is, Idx, 0, []).
-rewrite([{test,is_tuple,Fail,[Src]}=I1,
- {test,test_arity,Fail,[Src,N]}=I2|Is],Idx,Acc) ->
- case is_tagged_tuple(Is,Fail,Src,Idx) of
+rewrite([{test,test_arity,Fail,[Src,N]}=TA,
+ {test,is_tuple,Fail,[Src]}=TT|Is], Idx, Def, Acc0) ->
+ case is_tagged_tuple(Acc0, Def, Fail, Src, Idx) of
no ->
- rewrite(Is,Idx,[I2,I1|Acc]);
- {Atom,[{block,[]}|Is1]} ->
- rewrite(Is1,Idx,[{test,is_tagged_tuple,Fail,[Src,N,Atom]}|Acc]);
- {Atom,Is1} ->
- rewrite(Is1,Idx,[{test,is_tagged_tuple,Fail,[Src,N,Atom]}|Acc])
+ rewrite(Is, Idx, 0, [TT,TA|Acc0]);
+ {yes,Atom,Acc} ->
+ I = {test,is_tagged_tuple,Fail,[Src,N,Atom]},
+ rewrite(Is, Idx, Def, [I|Acc])
end;
-rewrite([I|Is],Idx,Acc) ->
- rewrite(Is,Idx,[I|Acc]);
-rewrite([],_,Acc) -> reverse(Acc).
-
-is_tagged_tuple([{block,[{set,[Dst],[Src],{get_tuple_element,0}}=B|Bs]},
- {test,is_eq_exact,Fail,[Dst,{atom,_}=Atom]}|Is],Fail,Src,Idx) ->
+rewrite([{block,[{'%def',Def}|Bl]}|Is], Idx, _Def, Acc) ->
+ rewrite(Is, Idx, Def, [{block,Bl}|Acc]);
+rewrite([{label,L}=I|Is], Idx0, Def, Acc) ->
+ Idx = beam_utils:index_label(L, Acc, Idx0),
+ rewrite(Is, Idx, Def, [I|Acc]);
+rewrite([I|Is], Idx, Def, Acc) ->
+ rewrite(Is, Idx, Def, [I|Acc]);
+rewrite([], _, _, Acc) -> Acc.
- %% if Dst is killed in the instruction stream and at fail label,
- %% we can safely remove get_tuple_element.
- %%
- %% if Dst is not killed in the stream, we cannot remove get_tuple_element
- %% since it is referenced.
-
- case is_killed(Dst,Is,Fail,Idx) of
- true -> {Atom,[{block,Bs}|Is]};
- false -> {Atom,[{block,[B|Bs]}|Is]}
+is_tagged_tuple([{block,Bl},
+ {test,is_eq_exact,Fail,[Dst,{atom,_}=Atom]}|Is],
+ Def, Fail, Src, Idx) ->
+ case is_tagged_tuple_1(Bl, Is, Fail, Src, Dst, Idx, Def, []) of
+ no ->
+ no;
+ {yes,[]} ->
+ {yes,Atom,Is};
+ {yes,[_|_]=Block} ->
+ {yes,Atom,[{block,Block}|Is]}
end;
-is_tagged_tuple([{block,[{set,_,_,_}=B|Bs]},
- {test,is_eq_exact,_,_}=I|Is],Fail,Src,Idx) ->
- case is_tagged_tuple([{block,Bs},I|Is],Fail,Src,Idx) of
- {Atom,[{block,Bsr}|Isr]} -> {Atom,[{block,[B|Bsr]}|Isr]};
- no -> no
+is_tagged_tuple(_, _, _, _, _) ->
+ no.
+
+is_tagged_tuple_1([{set,[Dst],[Src],{get_tuple_element,0}}=I|Bl],
+ Is, Fail, Src, Dst, Idx, Def, Acc) ->
+ %% Check usage of Dst to find out whether the get_tuple_element
+ %% is needed.
+ case usage(Dst, Is, Fail, Idx) of
+ killed ->
+ %% Safe to remove the get_tuple_element instruction.
+ {yes,reverse(Acc, Bl)};
+ used ->
+ %% Actively used. Must keep instruction.
+ {yes,reverse(Acc, [I|Bl])};
+ not_used ->
+ %% Not actually used (but must be initialized).
+ case is_defined(Dst, Def) of
+ false ->
+ %% Dst must be initialized, but the
+ %% actual value does not matter.
+ Kill = {set,[Dst],[nil],move},
+ {yes,reverse(Acc, [Kill|Bl])};
+ true ->
+ %% The register is previously initialized.
+ %% We can remove the instruction.
+ {yes,reverse(Acc, Bl)}
+ end
end;
-is_tagged_tuple(_Is,_Fail,_Src,_Idx) ->
+is_tagged_tuple_1([I|Bl], Is, Fail, Src, Dst, Idx, Def, Acc) ->
+ is_tagged_tuple_1(Bl, Is, Fail, Src, Dst, Idx, Def, [I|Acc]);
+is_tagged_tuple_1(_, _, _, _, _, _, _, _) ->
no.
-is_killed(Dst,Is,{_,Lbl},Idx) ->
- beam_utils:is_killed(Dst,Is,Idx) andalso
- beam_utils:is_killed_at(Dst,Lbl,Idx).
+usage(Dst, Is, Fail, Idx) ->
+ beam_utils:usage(Dst, [{test,is_number,Fail,[nil]}|Is], Idx).
+
+is_defined({x,X}, Def) ->
+ (Def bsr X) band 1 =:= 1.
diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl
index 910b7f6b0a..63bb57a1ac 100644
--- a/lib/compiler/src/beam_reorder.erl
+++ b/lib/compiler/src/beam_reorder.erl
@@ -35,8 +35,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = reorder(Is0),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 3d842a6fd3..e9f62a5765 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -43,8 +43,7 @@ function({function,Name,Arity,CLabel,Asm0}) ->
Asm = beam_utils:delete_live_annos(Asm3),
{function,Name,Arity,CLabel,Asm}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -117,14 +116,6 @@ simplify_basic_1([{test,is_tuple,_,[R]}=I|Is], Ts, Acc) ->
{tuple,_,_} -> simplify_basic_1(Is, Ts, Acc);
_ -> simplify_basic_1(Is, Ts, [I|Acc])
end;
-simplify_basic_1([{test,test_arity,_,[R,Arity]}=I|Is], Ts0, Acc) ->
- case tdb_find(R, Ts0) of
- {tuple,Arity,_} ->
- simplify_basic_1(Is, Ts0, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc])
- end;
simplify_basic_1([{test,is_map,_,[R]}=I|Is], Ts0, Acc) ->
case tdb_find(R, Ts0) of
map -> simplify_basic_1(Is, Ts0, Acc);
@@ -147,14 +138,6 @@ simplify_basic_1([{test,is_eq_exact,Fail,[R,{atom,_}=Atom]}=I|Is0], Ts0, Acc0) -
end,
Ts = update(I, Ts0),
simplify_basic_1(Is0, Ts, Acc);
-simplify_basic_1([{test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I|Is], Ts0, Acc) ->
- case tdb_find(R, Ts0) of
- {tuple,Arity,[Tag]} ->
- simplify_basic_1(Is, Ts0, Acc);
- _Other ->
- Ts = update(I, Ts0),
- simplify_basic_1(Is, Ts, [I|Acc])
- end;
simplify_basic_1([{select,select_val,Reg,_,_}=I0|Is], Ts, Acc) ->
I = case tdb_find(Reg, Ts) of
{integer,Range} ->
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index dd7ec4da96..60221578bd 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -22,15 +22,17 @@
-module(beam_utils).
-export([is_killed_block/2,is_killed/3,is_killed_at/3,
- is_not_used/3,
+ is_not_used/3,usage/3,
empty_label_index/0,index_label/3,index_labels/1,replace_labels/4,
code_at/2,bif_to_test/3,is_pure_test/1,
live_opt/1,delete_live_annos/1,combine_heap_needs/2,
- split_even/1]).
+ anno_defs/1,
+ split_even/1
+ ]).
-export_type([code_index/0,module_code/0,instruction/0]).
--import(lists, [map/2,member/2,sort/1,reverse/1,splitwith/2]).
+-import(lists, [flatmap/2,map/2,member/2,sort/1,reverse/1,splitwith/2]).
-define(is_const(Val), (Val =:= nil orelse
element(1, Val) =:= integer orelse
@@ -60,6 +62,23 @@
{lbl :: code_index(), %Label to code index.
res :: result_cache()}). %Result cache for each label.
+%% usage(Register, [Instruction], State) -> killed|not_used|used.
+%% Determine the usage of Register in the instruction sequence.
+%% The return value is one of:
+%%
+%% killed - The register is not used in any way.
+%% not_used - The register is referenced only by an allocating instruction
+%% (the actual value does not matter).
+%% used - The register is used (its value do matter).
+
+-spec usage(beam_asm:reg(), [instruction()], code_index()) ->
+ 'killed' | 'not_used' | 'used'.
+
+usage(R, Is, D) ->
+ St = #live{lbl=D,res=gb_trees:empty()},
+ {Usage,_} = check_liveness(R, Is, St),
+ Usage.
+
%% is_killed_block(Register, [Instruction]) -> true|false
%% Determine whether a register is killed by the instruction sequence inside
@@ -282,16 +301,33 @@ delete_live_annos([]) -> [].
%% combine_heap_needs(HeapNeed1, HeapNeed2) -> HeapNeed
%% Combine the heap need for two allocation instructions.
--spec combine_heap_needs(term(), term()) -> term().
+-type heap_need_tag() :: 'floats' | 'words'.
+-type heap_need() :: non_neg_integer() |
+ {'alloc',[{heap_need_tag(),non_neg_integer()}]}.
+-spec combine_heap_needs(heap_need(), heap_need()) -> heap_need().
-combine_heap_needs({alloc,Alloc1}, {alloc,Alloc2}) ->
- {alloc,combine_alloc_lists(Alloc1, Alloc2)};
-combine_heap_needs({alloc,Alloc}, Words) when is_integer(Words) ->
- {alloc,combine_alloc_lists(Alloc, [{words,Words}])};
-combine_heap_needs(Words, {alloc,Alloc}) when is_integer(Words) ->
- {alloc,combine_alloc_lists(Alloc, [{words,Words}])};
combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) ->
- H1+H2.
+ H1 + H2;
+combine_heap_needs(H1, H2) ->
+ combine_alloc_lists([H1,H2]).
+
+
+%% anno_defs(Instructions) -> Instructions'
+%% Add {'%def',RegisterBitmap} annotations to the beginning of
+%% each block. Iff bit X is set in the the bitmap, it means
+%% that {x,X} is defined when the block is entered.
+
+-spec anno_defs([instruction()]) -> [instruction()].
+
+anno_defs(Is0) ->
+ {Bef,[Fi|Is1]} =
+ splitwith(fun({func_info,_,_,_}) -> false;
+ (_) -> true
+ end, Is0),
+ {func_info,_,_,Arity} = Fi,
+ Regs = init_def_regs(Arity),
+ Is = defs(Is1, Regs, #{}),
+ Bef ++ [Fi|Is].
%% split_even/1
%% [1,2,3,4,5,6] -> {[1,3,5],[2,4,6]}
@@ -300,7 +336,6 @@ combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) ->
split_even(Rs) -> split_even(Rs, [], []).
-
%%%
%%% Local functions.
%%%
@@ -318,6 +353,10 @@ check_liveness(R, [{block,Blk}|Is], St0) ->
case check_liveness_block(R, Blk, St0) of
{transparent,St1} ->
check_liveness(R, Is, St1);
+ {alloc_used,St1} ->
+ %% Used by an allocating instruction, but value not referenced.
+ %% Must check the rest of the instructions.
+ not_used(check_liveness(R, Is, St1));
{Other,_}=Res when is_atom(Other) ->
Res
end;
@@ -376,9 +415,16 @@ check_liveness(R, [{bs_init,_,_,none,Ss,Dst}|Is], St) ->
check_liveness(R, [{bs_init,_,_,Live,Ss,Dst}|Is], St) ->
case R of
{x,X} ->
- case X < Live orelse member(R, Ss) of
- true -> {used,St};
- false -> {killed,St}
+ case member(R, Ss) of
+ true ->
+ {used,St};
+ false ->
+ if
+ X < Live ->
+ not_used(check_liveness(R, Is, St));
+ true ->
+ {killed,St}
+ end
end;
{y,_} ->
case member(R, Ss) of
@@ -547,6 +593,10 @@ check_liveness(R, [{allocate_zero,N,Live}|Is], St) ->
check_liveness(R, [{get_list,S,D1,D2}|Is], St) ->
I = {block,[{set,[D1,D2],[S],get_list}]},
check_liveness(R, [I|Is], St);
+check_liveness(R, [remove_message|Is], St) ->
+ check_liveness(R, Is, St);
+check_liveness({x,X}, [build_stacktrace|_], St) when X > 0 ->
+ {killed,St};
check_liveness(_R, Is, St) when is_list(Is) ->
%% Not implemented. Conservatively assume that the register is used.
{used,St}.
@@ -588,7 +638,7 @@ check_liveness_ret(R, R, St) -> {used,St};
check_liveness_ret(_, _, St) -> {killed,St}.
%% check_liveness_block(Reg, [Instruction], State) ->
-%% {killed | not_used | used | transparent,State'}
+%% {killed | not_used | used | alloc_used | transparent,State'}
%% Finds out how Reg is used in the instruction sequence inside a block.
%% Returns one of:
%% killed - Reg is assigned a new value or killed by an
@@ -596,6 +646,7 @@ check_liveness_ret(_, _, St) -> {killed,St}.
%% not_used - The value is not used, but the register is referenced
%% e.g. by an allocation instruction
%% transparent - Reg is neither used nor killed
+%% alloc_used - Used only in an allocate instruction
%% used - Reg is explicitly used by an instruction
%%
%% '%live' annotations are not allowed.
@@ -609,7 +660,7 @@ check_liveness_block({x,X}=R, [{set,Ds,Ss,{alloc,Live,Op}}|Is], St0) ->
true ->
case check_liveness_block_1(R, Ss, Ds, Op, Is, St0) of
{killed,St} -> {not_used,St};
- {transparent,St} -> {not_used,St};
+ {transparent,St} -> {alloc_used,St};
{_,_}=Res -> Res
end
end;
@@ -723,22 +774,18 @@ label(Old, D, Fb) ->
_ -> Fb(Old)
end.
-%% Help functions for combine_heap_needs.
-
-combine_alloc_lists(Al1, Al2) ->
- combine_alloc_lists_1(sort(Al1++Al2)).
+%% Help function for combine_heap_needs.
-combine_alloc_lists_1([{words,W1},{words,W2}|T])
- when is_integer(W1), is_integer(W2) ->
- [{words,W1+W2}|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([{floats,F1},{floats,F2}|T])
- when is_integer(F1), is_integer(F2) ->
- [{floats,F1+F2}|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([{words,_}=W|T]) ->
- [W|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([{floats,_}=F|T]) ->
- [F|combine_alloc_lists_1(T)];
-combine_alloc_lists_1([]) -> [].
+combine_alloc_lists(Al0) ->
+ Al1 = flatmap(fun(Words) when is_integer(Words) ->
+ [{words,Words}];
+ ({alloc,List}) ->
+ List
+ end, Al0),
+ Al2 = sofs:relation(Al1),
+ Al3 = sofs:relation_to_family(Al2),
+ Al4 = sofs:to_external(Al3),
+ [{Tag,lists:sum(L)} || {Tag,L} <- Al4].
%% live_opt/4.
@@ -781,6 +828,8 @@ live_opt([{block,Bl0}|Is], Regs0, D, Acc) ->
{Bl,Regs} = live_opt_block(reverse(Bl0), Regs0, D, [Live0]),
Live = {'%live',live_regs(Regs),Regs},
live_opt(Is, Regs, D, [{block,[Live|Bl]}|Acc]);
+live_opt([build_stacktrace=I|Is], _, D, Acc) ->
+ live_opt(Is, live_call(1), D, [I|Acc]);
live_opt([{label,L}=I|Is], Regs, D0, Acc) ->
D = gb_trees:insert(L, Regs, D0),
live_opt(Is, Regs, D, [I|Acc]);
@@ -951,3 +1000,208 @@ split_even([], Ss, Ds) ->
{reverse(Ss),reverse(Ds)};
split_even([S,D|Rs], Ss, Ds) ->
split_even(Rs, [S|Ss], [D|Ds]).
+
+%%%
+%%% Add annotations for defined registers.
+%%%
+%%% This analysis is done by scanning the instructions in
+%%% execution order.
+%%%
+
+defs([{apply,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{bif,_,{f,Fail},_Src,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
+defs([{block,Block0}|Is], Regs0, D0) ->
+ {Block,Regs,D} = defs_list(Block0, Regs0, D0),
+ [{block,[{'%def',Regs0}|Block]}|defs(Is, Regs, D)];
+defs([{bs_init,{f,L},_,_,_,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([{bs_put,{f,L},_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([build_stacktrace=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{call,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{call_ext,_,{extfunc,M,F,A}}=I|Is], _Regs, D) ->
+ case erl_bifs:is_exit_bif(M, F, A) of
+ false ->
+ [I|defs(Is, 1, D)];
+ true ->
+ [I|defs_unreachable(Is, D)]
+ end;
+defs([{call_ext,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{call_fun,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{'catch',_,{f,L}}=I|Is], Regs, D) ->
+ RegsAtLabel = init_def_regs(1),
+ [I|defs(Is, Regs, update_regs(L, RegsAtLabel, D))];
+defs([{catch_end,_}=I|Is], _Regs, D) ->
+ Regs = init_def_regs(1),
+ [I|defs(Is, Regs, D)];
+defs([{gc_bif,_,{f,Fail},Live,_Src,Dst}=I|Is], Regs0, D) ->
+ true = all_defined(Live, Regs0), %Assertion.
+ Regs = def_regs([Dst], init_def_regs(Live)),
+ [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
+defs([{get_map_elements,{f,L},_Src,{list,DstList}}=I|Is], Regs0, D) ->
+ {_,Ds} = beam_utils:split_even(DstList),
+ Regs = def_regs(Ds, Regs0),
+ [I|defs(Is, Regs, update_regs(L, Regs0, D))];
+defs([{get_tuple_element,_,_,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, D)];
+defs([{jump,{f,L}}=I|Is], Regs, D) ->
+ [I|defs_unreachable(Is, update_regs(L, Regs, D))];
+defs([{label,L}=I|Is], Regs0, D) ->
+ case D of
+ #{L:=Regs1} ->
+ Regs = Regs0 band Regs1,
+ [I|defs(Is, Regs, D)];
+ #{} ->
+ [I|defs(Is, Regs0, D)]
+ end;
+defs([{loop_rec,{f,L},{x,0}}=I|Is], _Regs, D0) ->
+ RegsAtLabel = init_def_regs(0),
+ D = update_regs(L, RegsAtLabel, D0),
+ [I|defs(Is, init_def_regs(1), D)];
+defs([{loop_rec_end,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 0, D)];
+defs([{make_fun2,_,_,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 1, D)];
+defs([{move,_,Dst}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, D)];
+defs([{put_map,{f,Fail},_,_,Dst,_,_}=I|Is], Regs0, D) ->
+ Regs = def_regs([Dst], Regs0),
+ [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
+defs([return=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{select,_,_Src,Fail,List}=I|Is], Regs, D0) ->
+ D = update_list([Fail|List], Regs, D0),
+ [I|defs_unreachable(Is, D)];
+defs([{test,_,{f,L},_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, update_regs(L, Regs, D))];
+defs([{test,_,{f,L},Live,_,Dst}=I|Is], Regs0, D) ->
+ true = all_defined(Live, Regs0), %Assertion.
+ Regs = def_regs([Dst], init_def_regs(Live)),
+ [I|defs(Is, Regs, update_regs(L, Regs0, D))];
+defs([{'try',_,{f,L}}=I|Is], Regs, D) ->
+ RegsAtLabel = init_def_regs(3),
+ [I|defs(Is, Regs, update_regs(L, RegsAtLabel, D))];
+defs([{try_case,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, init_def_regs(3), D)];
+defs([{wait,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{wait_timeout,_,_}=I|Is], _Regs, D) ->
+ [I|defs(Is, 0, D)];
+
+%% Exceptions.
+defs([{badmatch,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{case_end,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([if_end=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+defs([{try_case_end,_}=I|Is], _Regs, D) ->
+ [I|defs_unreachable(Is, D)];
+
+%% Neutral instructions
+defs([{bs_context_to_binary,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{bs_restore2,_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{bs_save2,_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{deallocate,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{kill,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{line,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{recv_mark,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{recv_set,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([timeout=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{trim,_,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{try_end,_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([{'%',_}=I|Is], Regs, D) ->
+ [I|defs(Is, Regs, D)];
+defs([], _, _) -> [].
+
+defs_unreachable([{label,L}=I|Is], D) ->
+ case D of
+ #{L:=Regs} ->
+ [I|defs(Is, Regs, D)];
+ #{} ->
+ defs_unreachable(Is, D)
+ end;
+defs_unreachable([_|Is], D) ->
+ defs_unreachable(Is, D);
+defs_unreachable([], _D) -> [].
+
+defs_list(Is, Regs, D) ->
+ defs_list(Is, Regs, D, []).
+
+defs_list([{set,Ds,_,{alloc,Live,Info}}=I|Is], Regs0, D0, Acc) ->
+ true = all_defined(Live, Regs0), %Assertion.
+ D = case Info of
+ {gc_bif,_,{f,Fail}} ->
+ update_regs(Fail, Regs0, D0);
+ {put_map,_,{f,Fail}} ->
+ update_regs(Fail, Regs0, D0);
+ _ ->
+ D0
+ end,
+ Regs = def_regs(Ds, init_def_regs(Live)),
+ defs_list(Is, Regs, D, [I|Acc]);
+defs_list([{set,Ds,_,Info}=I|Is], Regs0, D0, Acc) ->
+ D = case Info of
+ {bif,_,{f,Fail}} ->
+ update_regs(Fail, Regs0, D0);
+ {try_catch,'catch',{f,Fail}} ->
+ update_regs(Fail, init_def_regs(1), D0);
+ {try_catch,'try',{f,Fail}} ->
+ update_regs(Fail, init_def_regs(3), D0);
+ _ ->
+ D0
+ end,
+ Regs = def_regs(Ds, Regs0),
+ defs_list(Is, Regs, D, [I|Acc]);
+defs_list([], Regs, D, Acc) ->
+ {reverse(Acc),Regs,D}.
+
+init_def_regs(Arity) ->
+ (1 bsl Arity) - 1.
+
+def_regs([{x,X}|T], Regs) ->
+ def_regs(T, Regs bor (1 bsl X));
+def_regs([_|T], Regs) ->
+ def_regs(T, Regs);
+def_regs([], Regs) -> Regs.
+
+update_list([{f,L}|T], Regs, D0) ->
+ D = update_regs(L, Regs, D0),
+ update_list(T, Regs, D);
+update_list([_|T], Regs, D) ->
+ update_list(T, Regs, D);
+update_list([], _Regs, D) -> D.
+
+update_regs(L, Regs0, D) ->
+ case D of
+ #{L:=Regs1} ->
+ Regs = Regs0 band Regs1,
+ D#{L:=Regs};
+ #{} ->
+ D#{L=>Regs0}
+ end.
+
+all_defined(Live, Regs) ->
+ All = (1 bsl Live) - 1,
+ Regs band All =:= All.
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index be8908dd6b..2ad9747940 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -130,9 +130,8 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) ->
throw:Error ->
%% Controlled error.
[Error|validate_0(Module, Fs, Ft)];
- Class:Error ->
+ Class:Error:Stack ->
%% Crash.
- Stack = erlang:get_stacktrace(),
io:fwrite("Function: ~w/~w\n", [Name,Ar]),
erlang:raise(Class, Error, Stack)
end.
@@ -294,6 +293,8 @@ valfun_1({bs_context_to_binary,Ctx}, #vst{current=#st{x=Xs}}=Vst) ->
end;
valfun_1(bs_init_writable=I, Vst) ->
call(I, 1, Vst);
+valfun_1(build_stacktrace=I, Vst) ->
+ call(I, 1, Vst);
valfun_1({move,{y,_}=Src,{y,_}=Dst}, Vst) ->
%% The stack trimming optimization may generate a move from an initialized
%% but unassigned Y register to another Y register.
diff --git a/lib/compiler/src/beam_z.erl b/lib/compiler/src/beam_z.erl
index 787e33c142..1c56b95a9e 100644
--- a/lib/compiler/src/beam_z.erl
+++ b/lib/compiler/src/beam_z.erl
@@ -38,8 +38,7 @@ function({function,Name,Arity,CLabel,Is0}) ->
Is = undo_renames(Is0),
{function,Name,Arity,CLabel,Is}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index 327fecf0e6..770aa2c6c1 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -203,7 +203,12 @@ expand_opts(Opts0) ->
{_,_,undefined} -> [debug_info|Opts0];
{_,_,_} -> Opts0
end,
- foldr(fun expand_opt/2, [], Opts).
+ %% iff,unless processing is to complex...
+ Opts1 = case proplists:is_defined(makedep_side_effect,Opts) of
+ true -> proplists:delete(makedep,Opts);
+ false -> Opts
+ end,
+ foldr(fun expand_opt/2, [], Opts1).
expand_opt(basic_validation, Os) ->
[no_code_generation,to_pp,binary|Os];
@@ -674,6 +679,7 @@ select_list_passes_1([], _, Acc) ->
standard_passes() ->
[?pass(transform_module),
+ {iff,makedep_side_effect,?pass(makedep_and_output)},
{iff,makedep,[
?pass(makedep),
{unless,binary,?pass(makedep_output)}
@@ -1128,6 +1134,16 @@ core_lint_module(Code, St) ->
errors=St#compile.errors ++ Es}}
end.
+%% makedep + output and continue
+makedep_and_output(Code0, St) ->
+ {ok,DepCode,St1} = makedep(Code0,St),
+ case makedep_output(DepCode, St1) of
+ {ok,_IgnoreCode,St2} ->
+ {ok,Code0,St2};
+ {error,St2} ->
+ {error,St2}
+ end.
+
makedep(Code0, #compile{ifile=Ifile,ofile=Ofile,options=Opts}=St) ->
%% Get the target of the Makefile rule.
@@ -1530,15 +1546,14 @@ native_compile_1(Code, St) ->
{error,St#compile{errors=St#compile.errors ++ Es}}
end
catch
- Class:R ->
- Stk = erlang:get_stacktrace(),
+ Class:R:Stack ->
case IgnoreErrors of
true ->
Ws = [{St#compile.ifile,
- [{none,?MODULE,{native_crash,R,Stk}}]}],
+ [{none,?MODULE,{native_crash,R,Stack}}]}],
{ok,St#compile{warnings=St#compile.warnings ++ Ws}};
false ->
- erlang:raise(Class, R, Stk)
+ erlang:raise(Class, R, Stack)
end
end.
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index 7d3513c0ba..6e2114be56 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -353,12 +353,6 @@ expr(#c_case{arg=Arg,clauses=Cs}, Def, Rt, St0) ->
Pc = case_patcount(Cs),
St1 = body(Arg, Def, Pc, St0),
clauses(Cs, Def, Pc, Rt, St1);
-expr(#c_receive{clauses=Cs,timeout=#c_literal{val=infinity},
- action=#c_literal{}},
- Def, Rt, St) ->
- %% If the timeout is 'infinity', the after code can never
- %% be reached. We don't care if the return count is wrong.
- clauses(Cs, Def, 1, Rt, St);
expr(#c_receive{clauses=Cs,timeout=T,action=A}, Def, Rt, St0) ->
St1 = expr(T, Def, 1, St0),
St2 = body(A, Def, Rt, St1),
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index b5688de339..397e478e1e 100755
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -545,3 +545,12 @@ BEAM_FORMAT_NUMBER=0
## Test the arity of Reg and jumps to Lbl if it is not N.
## Test the first element of the tuple and jumps to Lbl if it is not Atom.
159: is_tagged_tuple/4
+
+# OTP 21
+
+## @spec build_stacktrace
+## @doc Given the raw stacktrace in x(0), build a cooked stacktrace suitable
+## for human consumption. Store it in x(0). Destroys all other registers.
+## Do a garbage collection if necessary to allocate space on the heap
+## for the result.
+160: build_stacktrace/0
diff --git a/lib/compiler/src/sys_core_alias.erl b/lib/compiler/src/sys_core_alias.erl
index 63e2f7488e..1bce1577d1 100644
--- a/lib/compiler/src/sys_core_alias.erl
+++ b/lib/compiler/src/sys_core_alias.erl
@@ -64,8 +64,7 @@ def({#c_var{name={F,Arity}}=Name,B0}) ->
erase(new_var_num),
{Name,B1}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end.
diff --git a/lib/compiler/src/sys_core_bsm.erl b/lib/compiler/src/sys_core_bsm.erl
index 3e04cc33df..37e071fafa 100644
--- a/lib/compiler/src/sys_core_bsm.erl
+++ b/lib/compiler/src/sys_core_bsm.erl
@@ -44,8 +44,7 @@ function([{#c_var{name={F,Arity}}=Name,B0}|Fs], FsAcc, Ws0) ->
{B,Ws} ->
function(Fs, [{Name,B}|FsAcc], Ws)
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end;
diff --git a/lib/compiler/src/sys_core_dsetel.erl b/lib/compiler/src/sys_core_dsetel.erl
index bd3eeae238..9e2df69b33 100644
--- a/lib/compiler/src/sys_core_dsetel.erl
+++ b/lib/compiler/src/sys_core_dsetel.erl
@@ -81,8 +81,7 @@ visit_module_1([{Name,F0}|Fs], Env, Acc) ->
{F,_} ->
visit_module_1(Fs, Env, [{Name,F}|Acc])
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
#c_var{name={Func,Arity}} = Name,
io:fwrite("Function: ~w/~w\n", [Func,Arity]),
erlang:raise(Class, Error, Stack)
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index df880ff784..e28d48acf5 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -125,8 +125,7 @@ function_1({#c_var{name={F,Arity}}=Name,B0}) ->
end, B0, 20),
{Name,B}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -415,6 +414,8 @@ expr(#c_call{module=M0,name=N0}=Call0, Ctxt, Sub) ->
no -> call(Call, M1, N1, Sub);
{yes,Seq} -> expr(Seq, Ctxt, Sub)
end;
+expr(#c_primop{name=#c_literal{val=build_stacktrace}}, effect, _Sub) ->
+ void();
expr(#c_primop{args=As0}=Prim, _, Sub) ->
As1 = expr_list(As0, value, Sub),
Prim#c_primop{args=As1};
@@ -2622,9 +2623,13 @@ delay_build_expr_1(#c_receive{clauses=Cs0,
timeout=Timeout,
action=A0}=Rec, TypeSig) ->
Cs = delay_build_cs(Cs0, TypeSig),
- A = case Timeout of
- #c_literal{val=infinity} -> A0;
- _ -> delay_build_expr(A0, TypeSig)
+ A = case {Timeout,A0} of
+ {#c_literal{val=infinity},#c_literal{}} ->
+ {_Type,Arity} = TypeSig,
+ Es = lists:duplicate(Arity, A0),
+ core_lib:make_values(Es);
+ _ ->
+ delay_build_expr(A0, TypeSig)
end,
Rec#c_receive{clauses=Cs,action=A};
delay_build_expr_1(#c_seq{body=B0}=Seq, TypeSig) ->
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index b222b25d7c..8f3399d133 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -77,10 +77,15 @@ functions(Forms, AtomMod) ->
function(#k_fdef{anno=#k{a=Anno},func=Name,arity=Arity,
vars=As,body=Kb}, AtomMod, St0) ->
try
- %% Annotate kernel records with variable usage.
#k_match{} = Kb, %Assertion.
+
+ %% Try to suppress the stack frame unless it is
+ %% really needed.
+ Body0 = avoid_stack_frame(Kb),
+
+ %% Annotate kernel records with variable usage.
Vdb0 = init_vars(As),
- {Body,_,Vdb} = body(Kb, 1, Vdb0),
+ {Body,_,Vdb} = body(Body0, 1, Vdb0),
%% Generate the BEAM assembly code.
{Asm,EntryLabel,St} = cg_fun(Body, As, Vdb, AtomMod,
@@ -88,12 +93,141 @@ function(#k_fdef{anno=#k{a=Anno},func=Name,arity=Arity,
Func = {function,Name,Arity,EntryLabel,Asm},
{Func,St}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
+
+%% avoid_stack_frame(Kernel) -> Kernel'
+%% If possible, avoid setting up a stack frame. Functions
+%% that only do matching, calls to guard BIFs, and tail-recursive
+%% calls don't need a stack frame.
+
+avoid_stack_frame(#k_match{body=Body}=M) ->
+ try
+ M#k_match{body=avoid_stack_frame_1(Body)}
+ catch
+ impossible ->
+ M
+ end.
+
+avoid_stack_frame_1(#k_alt{first=First0,then=Then0}=Alt) ->
+ First = avoid_stack_frame_1(First0),
+ Then = avoid_stack_frame_1(Then0),
+ Alt#k_alt{first=First,then=Then};
+avoid_stack_frame_1(#k_bif{op=Op}=Bif) ->
+ case Op of
+ #k_internal{} ->
+ %% Most internal BIFs clobber the X registers.
+ throw(impossible);
+ _ ->
+ Bif
+ end;
+avoid_stack_frame_1(#k_break{anno=Anno,args=Args}) ->
+ #k_guard_break{anno=Anno,args=Args};
+avoid_stack_frame_1(#k_guard_break{}=Break) ->
+ Break;
+avoid_stack_frame_1(#k_enter{}=Enter) ->
+ %% Tail-recursive calls don't need a stack frame.
+ Enter;
+avoid_stack_frame_1(#k_guard{clauses=Cs0}=Guard) ->
+ Cs = avoid_stack_frame_list(Cs0),
+ Guard#k_guard{clauses=Cs};
+avoid_stack_frame_1(#k_guard_clause{guard=G0,body=B0}=C) ->
+ G = avoid_stack_frame_1(G0),
+ B = avoid_stack_frame_1(B0),
+ C#k_guard_clause{guard=G,body=B};
+avoid_stack_frame_1(#k_match{anno=A,vars=Vs,body=B0,ret=Ret}) ->
+ %% Use #k_guard_match{} instead to avoid saving the X registers
+ %% to the stack before matching.
+ B = avoid_stack_frame_1(B0),
+ #k_guard_match{anno=A,vars=Vs,body=B,ret=Ret};
+avoid_stack_frame_1(#k_guard_match{body=B0}=M) ->
+ B = avoid_stack_frame_1(B0),
+ M#k_guard_match{body=B};
+avoid_stack_frame_1(#k_protected{arg=Arg0}=Prot) ->
+ Arg = avoid_stack_frame_1(Arg0),
+ Prot#k_protected{arg=Arg};
+avoid_stack_frame_1(#k_put{}=Put) ->
+ Put;
+avoid_stack_frame_1(#k_return{}=Ret) ->
+ Ret;
+avoid_stack_frame_1(#k_select{var=#k_var{anno=Vanno},types=Types0}=Select) ->
+ case member(reuse_for_context, Vanno) of
+ false ->
+ Types = avoid_stack_frame_list(Types0),
+ Select#k_select{types=Types};
+ true ->
+ %% Including binary patterns that overwrite the register containing
+ %% the binary with the match context may not be safe. For example,
+ %% bs_match_SUITE:bin_tail_e/1 with inlining will be rejected by
+ %% beam_validator.
+ %%
+ %% Essentially the following code is produced:
+ %%
+ %% bs_match {x,0} => {x,0}
+ %% ...
+ %% bs_match {x,0} => {x,1} %% ILLEGAL
+ %%
+ %% A bs_match instruction will only accept a match context as the
+ %% source operand if the source and destination registers are the
+ %% the same (as in the first bs_match instruction above).
+ %% The second bs_match instruction is therefore illegal.
+ %%
+ %% This situation is avoided if there is a stack frame:
+ %%
+ %% move {x,0} => {y,0}
+ %% bs_match {x,0} => {x,0}
+ %% ...
+ %% bs_match {y,0} => {x,1} %% LEGAL
+ %%
+ throw(impossible)
+ end;
+avoid_stack_frame_1(#k_seq{arg=#k_call{anno=Anno,op=Op}=Call,
+ body=#k_break{args=BrArgs0}}=Seq) ->
+ case Op of
+ #k_remote{mod=#k_atom{val=Mod},
+ name=#k_atom{val=Name},
+ arity=Arity} ->
+ case erl_bifs:is_exit_bif(Mod, Name, Arity) of
+ false ->
+ %% Will clobber X registers. Must have a stack frame.
+ throw(impossible);
+ true ->
+ %% The call to this BIF will never return. It is safe
+ %% to suppress the stack frame.
+ Bif = #k_bif{anno=Anno,
+ op=#k_internal{name=guard_error,arity=1},
+ args=[Call],ret=[]},
+ BrArgs = lists:duplicate(length(BrArgs0), #k_nil{}),
+ GB = #k_guard_break{anno=#k{us=[],ns=[],a=[]},args=BrArgs},
+ Seq#k_seq{arg=Bif,body=GB}
+ end;
+ _ ->
+ %% Will clobber X registers. Must have a stack frame.
+ throw(impossible)
+ end;
+avoid_stack_frame_1(#k_seq{arg=A0,body=B0}=Seq) ->
+ A = avoid_stack_frame_1(A0),
+ B = avoid_stack_frame_1(B0),
+ Seq#k_seq{arg=A,body=B};
+avoid_stack_frame_1(#k_test{}=Test) ->
+ Test;
+avoid_stack_frame_1(#k_type_clause{values=Values0}=TC) ->
+ Values = avoid_stack_frame_list(Values0),
+ TC#k_type_clause{values=Values};
+avoid_stack_frame_1(#k_val_clause{body=B0}=VC) ->
+ B = avoid_stack_frame_1(B0),
+ VC#k_val_clause{body=B};
+avoid_stack_frame_1(_Body) ->
+ throw(impossible).
+
+avoid_stack_frame_list([H|T]) ->
+ [avoid_stack_frame_1(H)|avoid_stack_frame_list(T)];
+avoid_stack_frame_list([]) -> [].
+
+
%% This pass creates beam format annotated with variable lifetime
%% information. Each thing is given an index and for each variable we
%% store the first and last index for its occurrence. The variable
@@ -219,10 +353,8 @@ expr(#k_put{anno=A}=Put, I, _Vdb) ->
Put#k_put{anno=#l{i=I,a=A#k.a}};
expr(#k_break{anno=A}=Break, I, _Vdb) ->
Break#k_break{anno=#l{i=I,a=A#k.a}};
-expr(#k_guard_break{anno=A}=Break, I, Vdb) ->
- Locked = [V || {V,_,_} <- Vdb],
- L = #l{i=I,a=A#k.a},
- Break#k_guard_break{anno=L,locked=Locked};
+expr(#k_guard_break{anno=A}=Break, I, _Vdb) ->
+ Break#k_guard_break{anno=#l{i=I,a=A#k.a}};
expr(#k_return{anno=A}=Ret, I, _Vdb) ->
Ret#k_return{anno=#l{i=I,a=A#k.a}}.
@@ -246,14 +378,9 @@ match(#k_alt{anno=A,first=Kf,then=Kt}, Ls, I, Vdb0) ->
F = match(Kf, Ls, I+1, Vdb1),
T = match(Kt, Ls, I+1, Vdb1),
#k_alt{anno=[],first=F,then=T};
-match(#k_select{anno=A,var=V,types=Kts}=Select, Ls0, I, Vdb0) ->
- Vanno = get_kanno(V),
- Ls1 = case member(no_usage, Vanno) of
- false -> add_element(V#k_var.name, Ls0);
- true -> Ls0
- end,
- Vdb1 = use_vars(union(A#k.us, Ls1), I, Vdb0),
- Ts = [type_clause(Tc, Ls1, I+1, Vdb1) || Tc <- Kts],
+match(#k_select{anno=A,types=Kts}=Select, Ls, I, Vdb0) ->
+ Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
+ Ts = [type_clause(Tc, Ls, I+1, Vdb1) || Tc <- Kts],
Select#k_select{anno=[],types=Ts};
match(#k_guard{anno=A,clauses=Kcs}, Ls, I, Vdb0) ->
Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
@@ -343,7 +470,7 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
put_reg(V, Reg)
end, [], Hvs),
stk=[]}, 0, Vdb),
- {B,_Aft,St} = cg_list(Les, 0, Vdb, Bef,
+ {B,_Aft,St} = cg_list(Les, Vdb, Bef,
St3#cg{bfail=0,
ultimate_failure=UltimateMatchFail,
is_top_block=true}),
@@ -388,26 +515,26 @@ cg(#k_return{anno=Le,args=Rs}, Vdb, Bef, St) ->
return_cg(Rs, Le, Vdb, Bef, St);
cg(#k_break{anno=Le,args=Bs}, Vdb, Bef, St) ->
break_cg(Bs, Le, Vdb, Bef, St);
-cg(#k_guard_break{anno=Le,args=Bs,locked=N}, Vdb, Bef, St) ->
- guard_break_cg(Bs, N, Le, Vdb, Bef, St);
+cg(#k_guard_break{anno=Le,args=Bs}, Vdb, Bef, St) ->
+ guard_break_cg(Bs, Le, Vdb, Bef, St);
cg(#cg_need_heap{h=H}, _Vdb, Bef, St) ->
{[{test_heap,H,max_reg(Bef#sr.reg)}],Bef,St}.
%% cg_list([Kexpr], FirstI, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-cg_list(Kes, I, Vdb, Bef, St0) ->
+cg_list(Kes, Vdb, Bef, St0) ->
{Keis,{Aft,St1}} =
flatmapfoldl(fun (Ke, {Inta,Sta}) ->
{Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
{Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes, I)),
+ end, {Bef,St0}, need_heap(Kes)),
{Keis,Aft,St1}.
%% need_heap([Lkexpr], I, St) -> [Lkexpr].
%% Insert need_heap instructions in Kexpr list. Try to be smart and
%% collect them together as much as possible.
-need_heap(Kes0, _I) ->
+need_heap(Kes0) ->
{Kes,H} = need_heap_0(reverse(Kes0), 0, []),
%% Prepend need_heap if necessary.
@@ -487,7 +614,10 @@ match_cg(M, Rs, Le, Vdb, Bef, St0) ->
guard_match_cg(M, Rs, Le, Vdb, Bef, St0) ->
I = Le#l.i,
{B,St1} = new_label(St0),
- #cg{bfail=Fail} = St1,
+ Fail = case St0 of
+ #cg{bfail=0,ultimate_failure=Fail0} -> Fail0;
+ #cg{bfail=Fail0} -> Fail0
+ end,
{Mis,Aft,St2} = match_cg(M, Fail, Bef, St1#cg{break=B}),
%% Update the register descriptors for the return registers.
Reg = guard_match_regs(Aft#sr.reg, Rs),
@@ -593,9 +723,6 @@ bsm_rename_ctx(#k_protected{arg=Ts0}=Prot, Old, New, _InProt) ->
InProt = true,
Ts = bsm_rename_ctx_list(Ts0, Old, New, InProt),
bsm_forget_var(Prot#k_protected{arg=Ts}, Old);
-bsm_rename_ctx(#k_match{body=Ms0}=Match, Old, New, InProt) ->
- Ms = bsm_rename_ctx(Ms0, Old, New, InProt),
- Match#k_match{body=Ms};
bsm_rename_ctx(#k_guard_match{body=Ms0}=Match, Old, New, InProt) ->
Ms = bsm_rename_ctx(Ms0, Old, New, InProt),
Match#k_guard_match{body=Ms};
@@ -612,9 +739,8 @@ bsm_rename_ctx(#cg_block{es=Es0}=Block, Old, New, true) ->
%% inside the block.
Es = bsm_rename_ctx_list(Es0, Old, New, true),
bsm_forget_var(Block#cg_block{es=Es}, Old);
-bsm_rename_ctx(#k_guard_break{locked=Locked0}=Break, Old, _New, _InProt) ->
- Locked = Locked0 -- [Old],
- bsm_forget_var(Break#k_guard_break{locked=Locked}, Old).
+bsm_rename_ctx(#k_guard_break{}=Break, Old, _New, _InProt) ->
+ bsm_forget_var(Break, Old).
bsm_rename_ctx_list([C|Cs], Old, New, InProt) ->
[bsm_rename_ctx(C, Old, New, InProt)|
@@ -639,26 +765,55 @@ block_cg(Es, Le, _Vdb, Bef, St) ->
block_cg(Es, Le, Bef, St).
block_cg(Es, Le, Bef, #cg{is_top_block=false}=St) ->
- cg_block(Es, Le#l.i, Le#l.vdb, Bef, St);
-block_cg(Es, Le, Bef, St0) ->
- {Is0,Aft,St} = cg_block(Es, Le#l.i, Le#l.vdb, Bef,
- St0#cg{is_top_block=false,need_frame=false}),
- Is = top_level_block(Is0, Aft, max_reg(Bef#sr.reg), St),
- {Is,Aft,St#cg{is_top_block=true}}.
-
-cg_block([], _I, _Vdb, Bef, St0) ->
+ cg_block(Es, Le#l.vdb, Bef, St);
+block_cg(Es, Le, Bef, #cg{is_top_block=true}=St0) ->
+ %% No stack frame has been established yet. Do we need one?
+ case need_stackframe(Es) of
+ true ->
+ %% We need a stack frame. Generate the code and add the
+ %% code for creating and deallocating the stack frame.
+ {Is0,Aft,St} = cg_block(Es, Le#l.vdb, Bef,
+ St0#cg{is_top_block=false,need_frame=false}),
+ Is = top_level_block(Is0, Aft, max_reg(Bef#sr.reg), St),
+ {Is,Aft,St#cg{is_top_block=true}};
+ false ->
+ %% This sequence of instructions ending in a #k_match{} (a
+ %% 'case' or 'if') in the Erlang code does not need a
+ %% stack frame yet. Delay the creation (if a stack frame
+ %% is needed at all, it will be created inside the
+ %% #k_match{}).
+ cg_list(Es, Le#l.vdb, Bef, St0)
+ end.
+
+%% need_stackframe([Kexpr]) -> true|false.
+%% Does this list of instructions need a stack frame?
+%%
+%% A sequence of instructions that don't clobber the X registers
+%% followed by a single #k_match{} doesn't need a stack frame.
+
+need_stackframe([H|T]) ->
+ case H of
+ #k_bif{op=#k_internal{}} -> true;
+ #k_put{arg=#k_binary{}} -> true;
+ #k_bif{} -> need_stackframe(T);
+ #k_put{} -> need_stackframe(T);
+ #k_guard_match{} -> need_stackframe(T);
+ #k_match{} when T =:= [] -> false;
+ _ -> true
+ end;
+need_stackframe([]) -> false.
+
+cg_block([], _Vdb, Bef, St0) ->
{[],Bef,St0};
-cg_block(Kes0, I, Vdb, Bef, St0) ->
+cg_block(Kes0, Vdb, Bef, St0) ->
{Kes2,Int1,St1} =
case basic_block(Kes0) of
{Kes1,LastI,Args,Rest} ->
- Ke = hd(Kes1),
- #l{i=Fb} = get_kanno(Ke),
- cg_basic_block(Kes1, Fb, LastI, Args, Vdb, Bef, St0);
+ cg_basic_block(Kes1, LastI, Args, Vdb, Bef, St0);
{Kes1,Rest} ->
- cg_list(Kes1, I, Vdb, Bef, St0)
+ cg_list(Kes1, Vdb, Bef, St0)
end,
- {Kes3,Int2,St2} = cg_block(Rest, I, Vdb, Int1, St1),
+ {Kes3,Int2,St2} = cg_block(Rest, Vdb, Int1, St1),
{Kes2 ++ Kes3,Int2,St2}.
basic_block(Kes) -> basic_block(Kes, []).
@@ -736,12 +891,12 @@ func_vars(_) -> [].
%% save_carefully/4 during code generation to only save the variables
%% that can be saved without growing the stack frame.
-cg_basic_block(Kes, Fb, Lf, As, Vdb, Bef, St0) ->
+cg_basic_block(Kes, Lf, As, Vdb, Bef, St0) ->
Int0 = reserve_arg_regs(As, Bef),
Int = extend_stack(Int0, Lf, Lf+1, Vdb),
{Keis,{Aft,St1}} =
flatmapfoldl(fun(Ke, St) -> cg_basic_block(Ke, St, Lf, Vdb) end,
- {Int,St0}, need_heap(Kes, Fb)),
+ {Int,St0}, need_heap(Kes)),
{Keis,Aft,St1}.
cg_basic_block(#cg_need_heap{}=Ke, {Bef,St0}, _Lf, Vdb) ->
@@ -1376,10 +1531,8 @@ guard_clause_cg(#k_guard_clause{anno=#l{vdb=Vdb},guard=G,body=B}, Fail, Bef, St0
%% the correct exit point. Primops and tests all go to the next
%% instruction on success or jump to a failure label.
-guard_cg(#k_protected{arg=Ts,ret=Rs,anno=#l{i=I,vdb=Pdb}}, Fail, _Vdb, Bef, St) ->
- protected_cg(Ts, Rs, Fail, I, Pdb, Bef, St);
-guard_cg(#cg_block{es=Ts,anno=#l{i=I,vdb=Bdb}}, Fail, _Vdb, Bef, St) ->
- guard_cg_list(Ts, Fail, I, Bdb, Bef, St);
+guard_cg(#k_protected{arg=Ts,ret=Rs,anno=#l{vdb=Pdb}}, Fail, _Vdb, Bef, St) ->
+ protected_cg(Ts, Rs, Fail, Pdb, Bef, St);
guard_cg(#k_test{anno=#l{i=I},op=Test0,args=As,inverted=Inverted},
Fail, Vdb, Bef, St0) ->
#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Test}} = Test0,
@@ -1397,6 +1550,18 @@ guard_cg(G, _Fail, Vdb, Bef, St) ->
%%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Aft}]),
{Gis,Aft,St1}.
+%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
+%% {[Ainstr],StackReg,St}.
+
+guard_cg_list(Kes, Fail, Vdb, Bef, St0) ->
+ {Keis,{Aft,St1}} =
+ flatmapfoldl(fun (Ke, {Inta,Sta}) ->
+ {Keis,Intb,Stb} =
+ guard_cg(Ke, Fail, Vdb, Inta, Sta),
+ {Keis,{Intb,Stb}}
+ end, {Bef,St0}, need_heap(Kes)),
+ {Keis,Aft,St1}.
+
%% protected_cg([Kexpr], [Ret], Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
%% Do a protected. Protecteds without return values are just done
%% for effect, the return value is not checked, success passes on to
@@ -1404,15 +1569,14 @@ guard_cg(G, _Fail, Vdb, Bef, St) ->
%% return values then these must be set to 'false' on failure,
%% control always passes to the next instruction.
-protected_cg(Ts, [], Fail, I, Vdb, Bef, St0) ->
+protected_cg(Ts, [], Fail, Vdb, Bef, St0) ->
%% Protect these calls, revert when done.
- {Tis,Aft,St1} = guard_cg_list(Ts, Fail, I, Vdb, Bef,
- St0#cg{bfail=Fail}),
+ {Tis,Aft,St1} = guard_cg_list(Ts, Fail, Vdb, Bef, St0#cg{bfail=Fail}),
{Tis,Aft,St1#cg{bfail=St0#cg.bfail}};
-protected_cg(Ts, Rs, _Fail, I, Vdb, Bef, St0) ->
+protected_cg(Ts, Rs, _Fail, Vdb, Bef, St0) ->
{Pfail,St1} = new_label(St0),
{Psucc,St2} = new_label(St1),
- {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, I, Vdb, Bef,
+ {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, Vdb, Bef,
St2#cg{bfail=Pfail}),
%%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Rs,I,Vdb,Aft}]),
%% Set return values to false.
@@ -1453,18 +1617,6 @@ test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
Aft = clear_dead(Bef, I, Vdb),
{[beam_utils:bif_to_test(Test, Args, {f,Fail})],Aft,St}.
-%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
-%% {[Ainstr],StackReg,St}.
-
-guard_cg_list(Kes, Fail, I, Vdb, Bef, St0) ->
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun (Ke, {Inta,Sta}) ->
- {Keis,Intb,Stb} =
- guard_cg(Ke, Fail, Vdb, Inta, Sta),
- {Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes, I)),
- {Keis,Aft,St1}.
-
%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,Aft,State}.
%% This is a special flatmapfoldl for match code gen where we
%% generate a "failure" label for each clause. The last clause uses
@@ -1685,9 +1837,25 @@ internal_cg(bs_init_writable=I, As, Rs, Le, Vdb, Bef, St) ->
{Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
{Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St};
+internal_cg(build_stacktrace=I, As, Rs, Le, Vdb, Bef, St) ->
+ %% This behaves like a function call.
+ {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
+ Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
+ {Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St};
internal_cg(raise, As, Rs, Le, Vdb, Bef, St) ->
%% raise can be treated like a guard BIF.
- bif_cg(raise, As, Rs, Le, Vdb, Bef, St).
+ bif_cg(raise, As, Rs, Le, Vdb, Bef, St);
+internal_cg(guard_error, [ExitCall], _Rs, Le, Vdb, Bef, St) ->
+ %% A call an exit BIF from inside a #k_guard_match{}.
+ %% Generate a standard call, but leave the register descriptors
+ %% alone, effectively pretending that there was no call.
+ #k_call{op=#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}},
+ args=As} = ExitCall,
+ Arity = length(As),
+ {Ms,_} = cg_call_args(As, Bef, Le#l.i, Vdb),
+ Call = {call_ext,Arity,{extfunc,Mod,Name,Arity}},
+ Is = Ms++[line(Le),Call],
+ {Is,Bef,St}.
%% bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
%% {[Ainstr],StackReg,State}.
@@ -1791,17 +1959,17 @@ cg_recv_wait(#k_atom{val=infinity}, #cg_block{anno=Le,es=Tes}, I, Bef, St0) ->
%% But to keep the stack and register information up to date,
%% we will generate the code for the 'after' body, and then discard it.
Int1 = clear_dead(Bef, I, Le#l.vdb),
- {_,Int2,St1} = cg_block(Tes, Le#l.i, Le#l.vdb,
+ {_,Int2,St1} = cg_block(Tes, Le#l.vdb,
Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
{[{wait,{f,St1#cg.recv}}],Int2,St1};
cg_recv_wait(#k_int{val=0}, #cg_block{anno=Le,es=Tes}, _I, Bef, St0) ->
- {Tis,Int,St1} = cg_block(Tes, Le#l.i, Le#l.vdb, Bef, St0),
+ {Tis,Int,St1} = cg_block(Tes, Le#l.vdb, Bef, St0),
{[timeout|Tis],Int,St1};
cg_recv_wait(Te, #cg_block{anno=Le,es=Tes}, I, Bef, St0) ->
Reg = cg_reg_arg(Te, Bef),
%% Must have empty registers here! Bug if anything in registers.
Int0 = clear_dead(Bef, I, Le#l.vdb),
- {Tis,Int,St1} = cg_block(Tes, Le#l.i, Le#l.vdb,
+ {Tis,Int,St1} = cg_block(Tes, Le#l.vdb,
Int0#sr{reg=clear_regs(Int0#sr.reg)}, St0),
{[{wait_timeout,{f,St1#cg.recv},Reg},timeout] ++ Tis,Int,St1}.
@@ -1862,7 +2030,7 @@ catch_cg(#cg_block{es=C}, #k_var{name=R}, Le, Vdb, Bef, St0) ->
CatchTag = Le#l.i,
Int1 = Bef#sr{stk=put_catch(CatchTag, Bef#sr.stk)},
CatchReg = fetch_stack({catch_tag,CatchTag}, Int1#sr.stk),
- {Cis,Int2,St2} = cg_block(C, Le#l.i, Le#l.vdb, Int1,
+ {Cis,Int2,St2} = cg_block(C, Le#l.vdb, Int1,
St1#cg{break=B,in_catch=true}),
[] = Int2#sr.reg, %Assertion.
Aft = Int2#sr{reg=[{0,R}],stk=drop_catch(CatchTag, Int2#sr.stk)},
@@ -2226,13 +2394,12 @@ break_cg(Bs, Le, Vdb, Bef, St) ->
{Ms ++ [{jump,{f,St#cg.break}}],
Int#sr{reg=clear_regs(Int#sr.reg)},St}.
-guard_break_cg(Bs, Locked, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
- RegLocked = get_locked_regs(Reg0, Locked),
- #sr{reg=Reg1} = Int = clear_dead(Bef#sr{reg=RegLocked}, I, Vdb),
+guard_break_cg(Bs, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
+ #sr{reg=Reg1} = Int = clear_dead(Bef, I, Vdb),
Reg2 = trim_free(Reg1),
NumLocked = length(Reg2),
Moves0 = gen_moves(Bs, Bef, NumLocked, []),
- Moves = order_moves(Moves0, find_scratch_reg(RegLocked)),
+ Moves = order_moves(Moves0, find_scratch_reg(Reg0)),
{BreakVars,_} = mapfoldl(fun(_, RegNum) ->
{{RegNum,gbreakvar},RegNum+1}
end, length(Reg2), Bs),
@@ -2240,20 +2407,6 @@ guard_break_cg(Bs, Locked, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
Aft = Int#sr{reg=Reg},
{Moves ++ [{jump,{f,St#cg.break}}],Aft,St}.
-get_locked_regs([R|Rs0], Preserve) ->
- case {get_locked_regs(Rs0, Preserve),R} of
- {[],{_,V}} ->
- case lists:member(V, Preserve) of
- true -> [R];
- false -> []
- end;
- {[],_} ->
- [];
- {Rs,_} ->
- [R|Rs]
- end;
-get_locked_regs([], _) -> [].
-
%% cg_reg_arg(Arg0, Info) -> Arg
%% cg_reg_args([Arg0], Info) -> [Arg]
%% Convert argument[s] into registers. Literal values are returned unchanged.
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 20cb3343fb..6029b91cdc 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -920,8 +920,9 @@ try_exception(Ecs0, St0) ->
%% Note that Tag is not needed for rethrow - it is already in Info.
{Evs,St1} = new_vars(3, St0), % Tag, Value, Info
{Ecs1,Ceps,St2} = clauses(Ecs0, St1),
+ Ecs2 = try_build_stacktrace(Ecs1, hd(Evs)),
[_,Value,Info] = Evs,
- LA = case Ecs1 of
+ LA = case Ecs2 of
[] -> [];
[C|_] -> get_lineno_anno(C)
end,
@@ -930,7 +931,7 @@ try_exception(Ecs0, St0) ->
body=[#iprimop{anno=#a{}, %Must have an #a{}
name=#c_literal{val=raise},
args=[Info,Value]}]},
- Hs = [#icase{anno=#a{anno=LA},args=[c_tuple(Evs)],clauses=Ecs1,fc=Ec}],
+ Hs = [#icase{anno=#a{anno=LA},args=[c_tuple(Evs)],clauses=Ecs2,fc=Ec}],
{Evs,Ceps++Hs,St2}.
try_after(As, St0) ->
@@ -946,6 +947,25 @@ try_after(As, St0) ->
Hs = [#icase{anno=#a{},args=[c_tuple(Evs)],clauses=[],fc=Ec}],
{Evs,Hs,St1}.
+try_build_stacktrace([#iclause{pats=Ps0,body=B0}=C0|Cs], RawStk) ->
+ [#c_tuple{es=[Class,Exc,Stk]}=Tup] = Ps0,
+ case Stk of
+ #c_var{name='_'} ->
+ %% Stacktrace variable is not used. Nothing to do.
+ [C0|try_build_stacktrace(Cs, RawStk)];
+ _ ->
+ %% Add code to build the stacktrace.
+ Ps = [Tup#c_tuple{es=[Class,Exc,RawStk]}],
+ Call = #iprimop{anno=#a{},
+ name=#c_literal{val=build_stacktrace},
+ args=[RawStk]},
+ Iset = #iset{var=Stk,arg=Call},
+ B = [Iset|B0],
+ C = C0#iclause{pats=Ps,body=B},
+ [C|try_build_stacktrace(Cs, RawStk)]
+ end;
+try_build_stacktrace([], _) -> [].
+
%% expr_bin([ArgExpr], St) -> {[Arg],[PreExpr],St}.
%% Flatten the arguments of a bin. Do this straight left to right!
%% Note that ibinary needs to have its annotation wrapped in a #a{}
@@ -2462,9 +2482,11 @@ cexpr(#icase{anno=A,args=Largs,clauses=Lcs,fc=Lfc}, As, St0) ->
cexpr(#ireceive1{anno=A,clauses=Lcs}, As, St0) ->
Exp = intersection(A#a.ns, As), %Exports
{Ccs,St1} = cclauses(Lcs, Exp, St0),
+ True = #c_literal{val=true},
+ Action = core_lib:make_values(lists:duplicate(1+length(Exp), True)),
{#c_receive{anno=A#a.anno,
clauses=Ccs,
- timeout=#c_literal{val=infinity},action=#c_literal{val=true}},
+ timeout=#c_literal{val=infinity},action=Action},
Exp,A#a.us,St1};
cexpr(#ireceive2{anno=A,clauses=Lcs,timeout=Lto,action=Les}, As, St0) ->
Exp = intersection(A#a.ns, As), %Exports
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 3eea058153..fd73e5a7dc 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -108,6 +108,7 @@ copy_anno(Kdst, Ksrc) ->
-record(iclause, {anno=[],isub,osub,pats,guard,body}).
-record(ireceive_accept, {anno=[],arg}).
-record(ireceive_next, {anno=[],arg}).
+-record(ignored, {anno=[]}).
-type warning() :: term(). % XXX: REFINE
@@ -162,8 +163,7 @@ function({#c_var{name={F,Arity}=FA},Body}, St0) ->
%%B1 = B0, St3 = St2, %Null second pass
{make_fdef(#k{us=[],ns=[],a=Ab}, F, Arity, Kvs, B1),St3}
catch
- Class:Error ->
- Stack = erlang:get_stacktrace(),
+ Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [F,Arity]),
erlang:raise(Class, Error, Stack)
end.
@@ -489,7 +489,7 @@ make_alt(First0, Then0) ->
Then1 = pre_seq(droplast(Then0), last(Then0)),
First2 = make_protected(First1),
Then2 = make_protected(Then1),
- Body = #k_atom{val=ignored},
+ Body = #ignored{},
First3 = #k_guard_clause{guard=First2,body=Body},
Then3 = #k_guard_clause{guard=Then2,body=Body},
First = #k_guard{clauses=[First3]},
@@ -2225,7 +2225,9 @@ ubody(E, return, St0) ->
{Ea,Pa,St1} = force_atomic(E, St0),
ubody(pre_seq(Pa, #ivalues{args=[Ea]}), return, St1)
end;
-ubody(E, {break,_Rs} = Break, St0) ->
+ubody(#ignored{}, {break,_} = Break, St) ->
+ ubody(#ivalues{args=[]}, Break, St);
+ubody(E, {break,[_]} = Break, St0) ->
%%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]),
%% Exiting expressions need no trailing break.
case is_exit_expr(E) of
@@ -2233,6 +2235,16 @@ ubody(E, {break,_Rs} = Break, St0) ->
false ->
{Ea,Pa,St1} = force_atomic(E, St0),
ubody(pre_seq(Pa, #ivalues{args=[Ea]}), Break, St1)
+ end;
+ubody(E, {break,Rs}=Break, St0) ->
+ case is_exit_expr(E) of
+ true ->
+ uexpr(E, return, St0);
+ false ->
+ {Vs,St1} = new_vars(length(Rs), St0),
+ Iset = #iset{vars=Vs,arg=E},
+ PreSeq = pre_seq([Iset], #ivalues{args=Vs}),
+ ubody(PreSeq, Break, St1)
end.
iletrec_funs(#iletrec{defs=Fs}, St0) ->
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index 87011b7680..7cd30b25a8 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -79,7 +79,7 @@
-record(k_guard_clause, {anno=[],guard,body}).
-record(k_break, {anno=[],args=[]}).
--record(k_guard_break, {anno=[],args=[],locked=[]}).
+-record(k_guard_break, {anno=[],args=[]}).
-record(k_return, {anno=[],args=[]}).
%%k_get_anno(Thing) -> element(2, Thing).
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 86146c614f..fe856b12b6 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -22,7 +22,8 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
integers/1,coverage/1,booleans/1,setelement/1,cons/1,
- tuple/1,record_float/1,binary_float/1,float_compare/1]).
+ tuple/1,record_float/1,binary_float/1,float_compare/1,
+ arity_checks/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -40,7 +41,8 @@ groups() ->
tuple,
record_float,
binary_float,
- float_compare
+ float_compare,
+ arity_checks
]}].
init_per_suite(Config) ->
@@ -171,6 +173,31 @@ do_float_compare(X) ->
_T -> Y > 0
end.
+arity_checks(_Config) ->
+ %% ERL-549: an unsafe optimization removed a test_arity instruction,
+ %% causing the following to return 'broken' instead of 'ok'.
+ ok = do_record_arity_check({rgb, 255, 255, 255, 1}),
+ ok = do_tuple_arity_check({255, 255, 255, 1}).
+
+-record(rgb, {r = 255, g = 255, b = 255}).
+
+do_record_arity_check(RGB) when
+ (element(2, RGB) >= 0), (element(2, RGB) =< 255),
+ (element(3, RGB) >= 0), (element(3, RGB) =< 255),
+ (element(4, RGB) >= 0), (element(4, RGB) =< 255) ->
+ if
+ element(1, RGB) =:= rgb, is_record(RGB, rgb) -> broken;
+ true -> ok
+ end.
+
+do_tuple_arity_check(RGB) when is_tuple(RGB),
+ (element(1, RGB) >= 0), (element(1, RGB) =< 255),
+ (element(2, RGB) >= 0), (element(2, RGB) =< 255),
+ (element(3, RGB) >= 0), (element(3, RGB) =< 255) ->
+ case RGB of
+ {255, _, _} -> broken;
+ _ -> ok
+ end.
id(I) ->
I.
diff --git a/lib/compiler/test/beam_utils_SUITE.erl b/lib/compiler/test/beam_utils_SUITE.erl
index 3a07f3923f..7686e69b63 100644
--- a/lib/compiler/test/beam_utils_SUITE.erl
+++ b/lib/compiler/test/beam_utils_SUITE.erl
@@ -25,7 +25,7 @@
is_not_killed/1,is_not_used_at/1,
select/1,y_catch/1,otp_8949_b/1,liveopt/1,coverage/1,
y_registers/1,user_predef/1,scan_f/1,cafu/1,
- receive_label/1]).
+ receive_label/1,read_size_file_version/1]).
-export([id/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -50,7 +50,8 @@ groups() ->
y_registers,
user_predef,
scan_f,
- cafu
+ cafu,
+ read_size_file_version
]}].
init_per_suite(Config) ->
@@ -121,6 +122,15 @@ bs_init(_Config) ->
{'EXIT',{badarg,_}} = (catch do_bs_init_2([0.5])),
{'EXIT',{badarg,_}} = (catch do_bs_init_2([-1])),
{'EXIT',{badarg,_}} = (catch do_bs_init_2([1 bsl 32])),
+
+ <<>> = do_bs_init_3({tag,0}, 0, 0),
+ <<0>> = do_bs_init_3({tag,0}, 2, 1),
+
+ <<"_build/shared">> = do_bs_init_4([], false),
+ <<"abc/shared">> = do_bs_init_4(<<"abc">>, false),
+ <<"foo/foo">> = do_bs_init_4(<<"foo">>, true),
+ error = do_bs_init_4([], not_boolean),
+
ok.
do_bs_init_1([?MODULE], Sz) ->
@@ -138,6 +148,45 @@ do_bs_init_2(SigNos) ->
erlang:error(badarg)
>>.
+do_bs_init_3({tag,Pos}, Offset, Len) ->
+ N0 = Offset - Pos,
+ N = if N0 > Len -> Len;
+ true -> N0
+ end,
+ <<0:N/unit:8>>.
+
+do_bs_init_4(Arg1, Arg2) ->
+ Build =
+ case id(Arg1) of
+ X when X =:= [] orelse X =:= false -> <<"_build">>;
+ X -> X
+ end,
+ case id(Arg2) of
+ true ->
+ id(<<case Build of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ id(Rewrite)
+ end/binary,
+ "/",
+ case id(<<"foo">>) of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ id(Rewrite)
+ end/binary>>);
+ false ->
+ id(<<case Build of
+ Rewrite when is_binary(Rewrite) ->
+ Rewrite;
+ Rewrite ->
+ id(Rewrite)
+ end/binary,
+ "/shared">>);
+ Other ->
+ error
+ end.
bs_save(_Config) ->
{a,30,<<>>} = do_bs_save(<<1:1,30:5>>),
@@ -445,5 +494,18 @@ do_receive_label(Rec) ->
do_receive_label(Rec)
end.
+read_size_file_version(_Config) ->
+ ok = do_read_size_file_version({ok,<<42>>}),
+ {ok,7777} = do_read_size_file_version({ok,<<7777:32>>}),
+ ok.
+
+do_read_size_file_version(E) ->
+ case E of
+ {ok,<<Version>>} when Version =:= 42 ->
+ ok;
+ {ok,<<MaxFiles:32>>} ->
+ {ok,MaxFiles}
+ end.
+
%% The identity function.
id(I) -> I.
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index c23514b36b..685eb2a72e 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -421,9 +421,9 @@ try_bin_opt(Mod) ->
try
do_bin_opt(Mod)
catch
- Class:Error ->
+ Class:Error:Stk ->
io:format("~p: ~p ~p\n~p\n",
- [Mod,Class,Error,erlang:get_stacktrace()]),
+ [Mod,Class,Error,Stk]),
error
end.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 39f9b5d063..7e1a432511 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -1590,14 +1590,16 @@ check_bitstring_list(_, _) ->
guard(_Config) ->
Tuple = id({a,b}),
ok = guard_1(<<1,2,3>>, {1,2,3}),
-
+ ok = guard_2(<<42>>, #{}),
ok.
%% Cover handling of #k_put{} in v3_codegen:bsm_rename_ctx/4.
-
guard_1(<<A,B,C>>, Tuple) when Tuple =:= {A,B,C} ->
ok.
+%% Cover handling of #k_call{} in v3_codegen:bsm_rename_ctx/4.
+guard_2(<<_>>, Healing) when Healing#{[] => Healing} =:= #{[] => #{}} ->
+ ok.
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index daebbe9d9d..35c11d894d 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -500,9 +500,8 @@ do_kernel_listing({M,A}) ->
io:format("*** compilation failure '~p' for module ~s\n",
[Error,M]),
error;
- Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -902,9 +901,8 @@ do_core_pp({M,A}, Outdir) ->
io:format("*** compilation failure '~p' for module ~s\n",
[Error,M]),
error;
- Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -961,9 +959,8 @@ do_core_roundtrip(Beam, Outdir) ->
io:format("*** compilation failure '~p' for file ~s\n",
[Error,Beam]),
error;
- Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [Beam,Class,Error,erlang:get_stacktrace()]),
+ Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [Beam,Class,Error,Stk]),
error
end.
@@ -1148,9 +1145,8 @@ do_asm(Beam, Outdir) ->
[Other,AsmFile]),
error
end
- catch Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ catch Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
@@ -1167,9 +1163,8 @@ do_opt_guards(Beam) ->
try
{ok,M,Asm} = compile:forms(A, ['S']),
do_opt_guards_mod(Asm)
- catch Class:Error ->
- io:format("~p: ~p ~p\n~p\n",
- [M,Class,Error,erlang:get_stacktrace()]),
+ catch Class:Error:Stk ->
+ io:format("~p: ~p ~p\n~p\n", [M,Class,Error,Stk]),
error
end.
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 7d2d58d5af..0d6f8c6f98 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1621,7 +1621,9 @@ type_tests() ->
is_reference,
is_port,
is_binary,
- is_function].
+ is_bitstring,
+ is_function,
+ is_map].
basic_andalso_orelse(Config) when is_list(Config) ->
T = id({type,integers,23,42}),
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index 5e90b79aa2..f15917e3cb 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -695,8 +695,28 @@ t_is_map(Config) when is_list(Config) ->
if is_map(#{b=>1}) -> ok end,
if not is_map([1,2,3]) -> ok end,
if not is_map(x) -> ok end,
+
+ ok = do_t_is_map(map, #{}),
+ error = do_t_is_map(map, {a,b,c}),
+ ok = do_t_is_map(number, 42),
+ ok = do_t_is_map(number, 42.0),
+ error = do_t_is_map(number, {a,b,c}),
ok.
+do_t_is_map(What, X) ->
+ B = case What of
+ map ->
+ %% Cover conversion of is_map/1 BIF to test instruction
+ %% in beam_utils:bif_to_test/3.
+ is_map(X);
+ number ->
+ is_number(X)
+ end,
+ case B of
+ true -> ok;
+ false -> error
+ end.
+
% test map updates without matching
t_update_literals(Config) when is_list(Config) ->
Map = #{x=>1,y=>2,z=>3,q=>4},
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index 35d2e8e91a..4b26a8dcdc 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -24,7 +24,8 @@
pmatch/1,mixed/1,aliases/1,non_matching_aliases/1,
match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1,
selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1,
- coverage/1,grab_bag/1,literal_binary/1]).
+ coverage/1,grab_bag/1,literal_binary/1,
+ unary_op/1]).
-include_lib("common_test/include/ct.hrl").
@@ -40,7 +41,7 @@ groups() ->
match_in_call,untuplify,
shortcut_boolean,letify_guard,selectify,deselectify,
underscore,match_map,map_vars_used,coverage,
- grab_bag,literal_binary]}].
+ grab_bag,literal_binary,unary_op]}].
init_per_suite(Config) ->
@@ -662,5 +663,74 @@ literal_binary_match(_, <<"x">>) -> 2;
literal_binary_match(_, <<"y">>) -> 3;
literal_binary_match(_, _) -> fail.
+unary_op(Config) ->
+ %% ERL-514. This test case only verifies that the code
+ %% calculates the correct result, not that the generated
+ %% code is optimial.
+
+ {non_associative,30} = unary_op_1('&'),
+ {non_associative,300} = unary_op_1('^'),
+ {non_associative,300} = unary_op_1('not'),
+ {non_associative,300} = unary_op_1('+'),
+ {non_associative,300} = unary_op_1('-'),
+ {non_associative,300} = unary_op_1('~~~'),
+ {non_associative,300} = unary_op_1('!'),
+ {non_associative,320} = unary_op_1('@'),
+
+ error = unary_op_1(Config),
+ error = unary_op_1(abc),
+ error = unary_op_1(42),
+
+ ok.
+
+unary_op_1(Vop@1) ->
+ %% If all optimizations are working as they should, there should
+ %% be no stack frame and all '=:=' tests should be coalesced into
+ %% a single select_val instruction.
+
+ case Vop@1 =:= '&' of
+ true ->
+ {non_associative,30};
+ false ->
+ case
+ case Vop@1 =:= '^' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= 'not' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= '+' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= '-' of
+ true ->
+ true;
+ false ->
+ case Vop@1 =:= '~~~' of
+ true ->
+ true;
+ false ->
+ Vop@1 =:= '!'
+ end
+ end
+ end
+ end
+ end
+ of
+ true ->
+ {non_associative,300};
+ false ->
+ case Vop@1 =:= '@' of
+ true ->
+ {non_associative,320};
+ false ->
+ error
+ end
+ end
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index b12bcbeeab..d93c5dda1e 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -318,8 +318,7 @@ expect_error(Fun) ->
io:format("~p", [Any]),
ct:fail(call_was_supposed_to_fail)
catch
- Class:Reason ->
- Stk = erlang:get_stacktrace(),
+ Class:Reason:Stk ->
io:format("~p:~p\n~p\n", [Class,Reason,Stk]),
case {Class,Reason} of
{error,undef} ->
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index 8304672558..5e386790c0 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -222,9 +222,8 @@ do_ref_opt(Source, PrivDir) ->
collect_recv_opt_instrs(Code)
end,
ok
- catch Class:Error ->
- io:format("~s: ~p ~p\n~p\n",
- [Source,Class,Error,erlang:get_stacktrace()]),
+ catch Class:Error:Stk ->
+ io:format("~s: ~p ~p\n~p\n", [Source,Class,Error,Stk]),
error
end.
@@ -265,6 +264,10 @@ export(Config) when is_list(Config) ->
self() ! {result,Ref,42},
42 = export_1(Ref),
{error,timeout} = export_1(Ref),
+
+ self() ! {result,Ref},
+ {ok,Ref} = export_2(),
+
ok.
export_1(Reference) ->
@@ -281,6 +284,10 @@ export_1(Reference) ->
id({build,self()}),
Result.
+export_2() ->
+ receive {result,Result} -> ok end,
+ {ok,Result}.
+
wait(Config) when is_list(Config) ->
self() ! <<42>>,
<<42>> = wait_1(r, 1, 2),
diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl
index 42dbf7d5f0..8cf7928cc4 100644
--- a/lib/compiler/test/trycatch_SUITE.erl
+++ b/lib/compiler/test/trycatch_SUITE.erl
@@ -26,7 +26,8 @@
nested_of/1,nested_catch/1,nested_after/1,
nested_horrid/1,last_call_optimization/1,bool/1,
plain_catch_coverage/1,andalso_orelse/1,get_in_try/1,
- hockey/1,handle_info/1,catch_in_catch/1,grab_bag/1]).
+ hockey/1,handle_info/1,catch_in_catch/1,grab_bag/1,
+ stacktrace/1,nested_stacktrace/1]).
-include_lib("common_test/include/ct.hrl").
@@ -42,7 +43,8 @@ groups() ->
after_oops,eclectic,rethrow,nested_of,nested_catch,
nested_after,nested_horrid,last_call_optimization,
bool,plain_catch_coverage,andalso_orelse,get_in_try,
- hockey,handle_info,catch_in_catch,grab_bag]}].
+ hockey,handle_info,catch_in_catch,grab_bag,
+ stacktrace,nested_stacktrace]}].
init_per_suite(Config) ->
@@ -1039,5 +1041,123 @@ grab_bag(_Config) ->
ok.
+stacktrace(_Config) ->
+ V = [make_ref()|self()],
+ case ?MODULE:module_info(native) of
+ false ->
+ {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ {caught2,{error,badarith},[{erlang,'+',[0,a],_},
+ {?MODULE,my_add,2,_}|_]} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}});
+ true ->
+ {value2,{caught1,badarg,[{?MODULE,my_abs,1,_}|_]}} =
+ stacktrace_1({'abs',V}, error, {value,V}),
+ {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]} =
+ stacktrace_1({'div',{1,0}}, error, {'add',{0,a}})
+ end,
+ {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]} =
+ stacktrace_1({value,V}, error, {value,V}),
+ {caught2,{throw,V},[{?MODULE,foo,1,_}|_]} =
+ stacktrace_1({value,V}, error, {throw,V}),
+
+ try
+ stacktrace_2()
+ catch
+ error:{badmatch,_}:Stk2 ->
+ [{?MODULE,stacktrace_2,0,_},
+ {?MODULE,stacktrace,1,_}|_] = Stk2,
+ Stk2 = erlang:get_stacktrace(),
+ ok
+ end,
+
+ try
+ stacktrace_3(a, b)
+ catch
+ error:function_clause:Stk3 ->
+ Stk3 = erlang:get_stacktrace(),
+ case lists:module_info(native) of
+ false ->
+ [{lists,prefix,[a,b],_}|_] = Stk3;
+ true ->
+ [{lists,prefix,2,_}|_] = Stk3
+ end
+ end,
+
+ try
+ throw(x)
+ catch
+ throw:x:IntentionallyUnused ->
+ ok
+ end.
+
+stacktrace_1(X, C1, Y) ->
+ try try foo(X) of
+ C1 -> value1
+ catch
+ C1:D1:Stk1 ->
+ Stk1 = erlang:get_stacktrace(),
+ {caught1,D1,Stk1}
+ after
+ foo(Y)
+ end of
+ V2 -> {value2,V2}
+ catch
+ C2:D2:Stk2 -> {caught2,{C2,D2},Stk2=erlang:get_stacktrace()}
+ end.
+
+stacktrace_2() ->
+ ok = erlang:process_info(self(), current_function),
+ ok.
+
+stacktrace_3(A, B) ->
+ {ok,lists:prefix(A, B)}.
+
+nested_stacktrace(_Config) ->
+ V = [{make_ref()}|[self()]],
+ value1 = nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
+ {void,void,void}),
+ case ?MODULE:module_info(native) of
+ false ->
+ {caught1,
+ [{erlang,'+',[V,x1],_},{?MODULE,my_add,2,_}|_],
+ value2} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ {caught1,
+ [{erlang,'+',[V,x1],_},{?MODULE,my_add,2,_}|_],
+ {caught2,[{erlang,abs,[V],_}|_]}} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg});
+ true ->
+ {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ value2} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{value,{V,x2}},void,{V,x2}}),
+ {caught1,
+ [{?MODULE,my_add,2,_}|_],
+ {caught2,[{?MODULE,my_abs,1,_}|_]}} =
+ nested_stacktrace_1({{'add',{V,x1}},error,badarith},
+ {{'abs',V},error,badarg})
+ end,
+ ok.
+
+nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
+ try foo(X1) of
+ V1 -> value1
+ catch
+ C1:V1:S1 ->
+ S1 = erlang:get_stacktrace(),
+ T2 = try foo(X2) of
+ V2 -> value2
+ catch
+ C2:V2:S2 ->
+ S2 = erlang:get_stacktrace(),
+ {caught2,S2}
+ end,
+ {caught1,S1,T2}
+ end.
+
id(I) -> I.
diff --git a/lib/compiler/test/z_SUITE.erl b/lib/compiler/test/z_SUITE.erl
index d864184f4c..cd95d0e733 100644
--- a/lib/compiler/test/z_SUITE.erl
+++ b/lib/compiler/test/z_SUITE.erl
@@ -54,8 +54,7 @@ do_loaded([{M,_}|Ms], E0) ->
_ = M:module_info(functions),
E0
catch
- C:Error ->
- Stk = erlang:get_stacktrace(),
+ C:Error:Stk ->
io:format("~p:~p\n~p\n", [C,Error,Stk]),
E0 + 1
end,
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 435a57aac2..082786c7d8 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.1.3
+COMPILER_VSN = 7.1.4
diff --git a/lib/cosEvent/doc/src/notes.xml b/lib/cosEvent/doc/src/notes.xml
index fe94cb64d3..ba0b0d88db 100644
--- a/lib/cosEvent/doc/src/notes.xml
+++ b/lib/cosEvent/doc/src/notes.xml
@@ -33,7 +33,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosEvent 2.2.1</title>
+ <section><title>cosEvent 2.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosEvent 2.2.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosEvent/vsn.mk b/lib/cosEvent/vsn.mk
index c39bed9fe4..578950294a 100644
--- a/lib/cosEvent/vsn.mk
+++ b/lib/cosEvent/vsn.mk
@@ -1,2 +1,2 @@
-COSEVENT_VSN = 2.2.1
+COSEVENT_VSN = 2.2.2
diff --git a/lib/cosEventDomain/doc/src/notes.xml b/lib/cosEventDomain/doc/src/notes.xml
index 5e5bb2c33e..bd0a119ad2 100644
--- a/lib/cosEventDomain/doc/src/notes.xml
+++ b/lib/cosEventDomain/doc/src/notes.xml
@@ -32,7 +32,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosEventDomain 1.2.1</title>
+ <section><title>cosEventDomain 1.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosEventDomain 1.2.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosEventDomain/vsn.mk b/lib/cosEventDomain/vsn.mk
index 4e10d6ac60..0c063a00f9 100644
--- a/lib/cosEventDomain/vsn.mk
+++ b/lib/cosEventDomain/vsn.mk
@@ -1,2 +1,2 @@
-COSEVENTDOMAIN_VSN = 1.2.1
+COSEVENTDOMAIN_VSN = 1.2.2
diff --git a/lib/cosFileTransfer/doc/src/notes.xml b/lib/cosFileTransfer/doc/src/notes.xml
index 58ab087014..e0b4bdf64b 100644
--- a/lib/cosFileTransfer/doc/src/notes.xml
+++ b/lib/cosFileTransfer/doc/src/notes.xml
@@ -31,7 +31,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosFileTransfer 1.2.1</title>
+ <section><title>cosFileTransfer 1.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosFileTransfer 1.2.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosFileTransfer/vsn.mk b/lib/cosFileTransfer/vsn.mk
index e271c05242..561f11fbb2 100644
--- a/lib/cosFileTransfer/vsn.mk
+++ b/lib/cosFileTransfer/vsn.mk
@@ -1 +1 @@
-COSFILETRANSFER_VSN = 1.2.1
+COSFILETRANSFER_VSN = 1.2.2
diff --git a/lib/cosNotification/doc/src/notes.xml b/lib/cosNotification/doc/src/notes.xml
index 1237000153..bf0fc73548 100644
--- a/lib/cosNotification/doc/src/notes.xml
+++ b/lib/cosNotification/doc/src/notes.xml
@@ -32,7 +32,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosNotification 1.2.2</title>
+ <section><title>cosNotification 1.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosNotification 1.2.2</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosNotification/vsn.mk b/lib/cosNotification/vsn.mk
index 0d95ab4853..1677057670 100644
--- a/lib/cosNotification/vsn.mk
+++ b/lib/cosNotification/vsn.mk
@@ -1,2 +1,2 @@
-COSNOTIFICATION_VSN = 1.2.2
+COSNOTIFICATION_VSN = 1.2.3
diff --git a/lib/cosProperty/doc/src/notes.xml b/lib/cosProperty/doc/src/notes.xml
index e5d22982c5..4de246de67 100644
--- a/lib/cosProperty/doc/src/notes.xml
+++ b/lib/cosProperty/doc/src/notes.xml
@@ -33,7 +33,22 @@
</header>
- <section><title>cosProperty 1.2.2</title>
+ <section><title>cosProperty 1.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosProperty 1.2.2</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosProperty/vsn.mk b/lib/cosProperty/vsn.mk
index 78ba88445d..a3a952346e 100644
--- a/lib/cosProperty/vsn.mk
+++ b/lib/cosProperty/vsn.mk
@@ -1,2 +1,2 @@
-COSPROPERTY_VSN = 1.2.2
+COSPROPERTY_VSN = 1.2.3
diff --git a/lib/cosTime/doc/src/notes.xml b/lib/cosTime/doc/src/notes.xml
index 686d9e6add..16e02f8b1f 100644
--- a/lib/cosTime/doc/src/notes.xml
+++ b/lib/cosTime/doc/src/notes.xml
@@ -33,7 +33,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosTime 1.2.2</title>
+ <section><title>cosTime 1.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosTime 1.2.2</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosTime/vsn.mk b/lib/cosTime/vsn.mk
index 7c9cae2d2f..7d6fcbebcd 100644
--- a/lib/cosTime/vsn.mk
+++ b/lib/cosTime/vsn.mk
@@ -1,2 +1,2 @@
-COSTIME_VSN = 1.2.2
+COSTIME_VSN = 1.2.3
diff --git a/lib/cosTransactions/doc/src/notes.xml b/lib/cosTransactions/doc/src/notes.xml
index 85ace1208b..2401c04c3f 100644
--- a/lib/cosTransactions/doc/src/notes.xml
+++ b/lib/cosTransactions/doc/src/notes.xml
@@ -33,7 +33,22 @@
<file>notes.xml</file>
</header>
- <section><title>cosTransactions 1.3.2</title>
+ <section><title>cosTransactions 1.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>cosTransactions 1.3.2</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/cosTransactions/vsn.mk b/lib/cosTransactions/vsn.mk
index ab163d83c2..bba2058231 100644
--- a/lib/cosTransactions/vsn.mk
+++ b/lib/cosTransactions/vsn.mk
@@ -1 +1 @@
-COSTRANSACTIONS_VSN = 1.3.2
+COSTRANSACTIONS_VSN = 1.3.3
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 9376e6f649..dbeb886d7b 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,76 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The compatibility function <c>void HMAC_CTX_free</c> in
+ <c>crypto.c</c> erroneously tried to return a value.</p>
+ <p>
+ Own Id: OTP-14720</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Rewrite public and private key encode/decode with EVP
+ api. New RSA padding options added. This is a modified
+ half of PR-838.</p>
+ <p>
+ Own Id: OTP-14446</p>
+ </item>
+ <item>
+ <p>
+ The crypto API is extended to use private/public keys
+ stored in an Engine for sign/verify or encrypt/decrypt
+ operations.</p>
+ <p>
+ The ssl application provides an API to use this new
+ engine concept in TLS.</p>
+ <p>
+ Own Id: OTP-14448</p>
+ </item>
+ <item>
+ <p> Add support to plug in alternative implementations
+ for some or all of the cryptographic operations supported
+ by the OpenSSL Engine API. When configured appropriately,
+ OpenSSL calls the engine's implementation of these
+ operations instead of its own. </p>
+ <p>
+ Own Id: OTP-14567</p>
+ </item>
+ <item>
+ <p>
+ Replaced a call of the OpenSSL deprecated function
+ <c>DH_generate_parameters</c> in <c>crypto.c</c>.</p>
+ <p>
+ Own Id: OTP-14639</p>
+ </item>
+ <item>
+ <p>
+ Documentation added about how to use keys stored in an
+ Engine.</p>
+ <p>
+ Own Id: OTP-14735 Aux Id: OTP-14448 </p>
+ </item>
+ <item>
+ <p> Add engine_ ctrl_cmd_string/3,4 the OpenSSL Engine
+ support in crypto. </p>
+ <p>
+ Own Id: OTP-14801</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 1dceebb4e4..da3915a4fc 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.1
+CRYPTO_VSN = 4.2
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 21fe7d449d..e71746e30d 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -33,6 +33,21 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 4.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Do not quote variables and button names in Debugger
+ windows. The bug was introduced in Erlang/OTP 20.1. </p>
+ <p>
+ Own Id: OTP-14802</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 4.2.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index 72cedb2240..57da7e5618 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 4.2.3
+DEBUGGER_VSN = 4.2.4
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 6a6e65cb94..a1eecfb3fe 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -32,6 +32,29 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 3.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The error message returned from Dialyzer when, for
+ example, a modified record field type is not a subtype of
+ the declared type, no longer includes a call stack. The
+ bug was introduced in Erlang/OTP 19.3. </p>
+ <p>
+ Own Id: OTP-14742</p>
+ </item>
+ <item>
+ <p> A bug relating to maps and never returning functions
+ has been fixed. </p>
+ <p>
+ Own Id: OTP-14743</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 3.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 8367432ac5..93cfea3c5e 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -299,6 +299,7 @@ traverse(Tree, Map, State) ->
match_fail -> t_none();
raise -> t_none();
bs_init_writable -> t_from_term(<<>>);
+ build_stacktrace -> t_list();
Other -> erlang:error({'Unsupported primop', Other})
end,
{State, Map, Type};
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index d03326ec97..b1f6a54503 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -418,6 +418,7 @@ traverse(Tree, DefinedVars, State) ->
match_fail -> throw(error);
raise -> throw(error);
bs_init_writable -> {State, t_from_term(<<>>)};
+ build_stacktrace -> {State, t_list()};
Other -> erlang:error({'Unsupported primop', Other})
end;
'receive' ->
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index d130b14fec..1b46f66602 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 3.2.2
+DIALYZER_VSN = 3.2.3
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index eded788419..ba4525fd20 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -43,6 +43,22 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 2.1.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix documentation typo: peer_down/3 was written where
+ peer_down/3 was intended.</p>
+ <p>
+ Own Id: OTP-14805</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.1.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/doc/src/seealso.ent b/lib/diameter/doc/src/seealso.ent
index c5a53670d0..72d74c103c 100644
--- a/lib/diameter/doc/src/seealso.ent
+++ b/lib/diameter/doc/src/seealso.ent
@@ -79,7 +79,7 @@ significant.
<!ENTITY app_handle_answer '<seealso marker="diameter_app#Mod:handle_answer-4">handle_answer/4</seealso>'>
<!ENTITY app_handle_request '<seealso marker="diameter_app#Mod:handle_request-3">handle_request/3</seealso>'>
<!ENTITY app_handle_error '<seealso marker="diameter_app#Mod:handle_error-4">handle_error/4</seealso>'>
-<!ENTITY app_peer_down '<seealso marker="diameter_app#Mod:peer_down-3">peer_up/3</seealso>'>
+<!ENTITY app_peer_down '<seealso marker="diameter_app#Mod:peer_down-3">peer_down/3</seealso>'>
<!ENTITY app_peer_up '<seealso marker="diameter_app#Mod:peer_up-3">peer_up/3</seealso>'>
<!ENTITY app_pick_peer '<seealso marker="diameter_app#Mod:pick_peer-4">pick_peer/4</seealso>'>
<!ENTITY app_prepare_retransmit '<seealso marker="diameter_app#Mod:prepare_retransmit-3">prepare_retransmit/3</seealso>'>
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index d0e58e8410..7da59f8b25 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -56,7 +56,8 @@
{"2.0", [{restart_application, diameter}]}, %% 20.0
{"2.1", [{load_module, diameter_gen}, %% 20.1
{update, diameter_reg, {advanced, "2.1"}}]},
- {"2.1.1", [{load_module, diameter_gen}]}
+ {"2.1.1", [{load_module, diameter_gen}]}, %% 20.1.2
+ {"2.1.2", []} %% 20.1.3
],
[
{"0.9", [{restart_application, diameter}]},
@@ -93,6 +94,7 @@
{"1.12.2", [{restart_application, diameter}]},
{"2.0", [{restart_application, diameter}]},
{"2.1", [{restart_application, diameter}]},
- {"2.1.1", [{load_module, diameter_gen}]}
+ {"2.1.1", [{load_module, diameter_gen}]},
+ {"2.1.2", []}
]
}.
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index bfb260ed8f..0c852d75cd 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 2.1.2
+DIAMETER_VSN = 2.1.3
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 96d7597d83..240789e876 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.9.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The map type is correctly denoted as <c>map()</c> in
+ function specifications and types. </p>
+ <p>
+ Own Id: OTP-14777</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.9.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index 065944ccef..2f6d469536 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.9.1
+EDOC_VSN = 0.9.2
diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml
index 7aad745f67..8b066671ee 100644
--- a/lib/eldap/doc/src/notes.xml
+++ b/lib/eldap/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Eldap application.</p>
+<section><title>Eldap 1.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
index 721387d97d..1636b6bb6d 100644
--- a/lib/eldap/vsn.mk
+++ b/lib/eldap/vsn.mk
@@ -1 +1 @@
-ELDAP_VSN = 1.2.2
+ELDAP_VSN = 1.2.3
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 59c65665d4..2652b4b0c8 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -31,7 +31,26 @@
</header>
<p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 0.7.1</title>
+ <section><title>Erl_Docgen 0.7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> The style for code, warning and note tags in the pdf
+ have been changed so they look like the html version.
+ <br/> The spacing around code blocks have been changed
+ for both html and pdf so it's the same regardless if the
+ user have a newline after the start tag (or before the
+ end tag) or not. </p>
+ <p>
+ Own Id: OTP-14674</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.7.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 17a7c483f4..95b2329ac5 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 0.7.1
+ERL_DOCGEN_VSN = 0.7.2
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index ec20f3c67f..641a3de13f 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.10.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 01fcee86dd..d76d110afd 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 3.10
+EI_VSN = 3.10.1
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index 7133befe37..b38cb2e70e 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -33,6 +33,21 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.3.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.3.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index 25bb0dec17..2ed9eaac16 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.3.4
+EUNIT_VSN = 2.3.5
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index eadaee50e2..bad0c254ce 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -31,6 +31,39 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.17</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix bug for hipe compiled code using
+ <c>&lt;&lt;X/utf32&gt;&gt;</c> binary construction that
+ could cause faulty result or even VM crash.</p>
+ <p>
+ On architectures other than x86_64, code need to be
+ recompiled to benefit from this fix.</p>
+ <p>
+ Own Id: OTP-14740</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added documentation about limitations of hipe compared to
+ beam compiled code.</p>
+ <p>
+ Own Id: OTP-14767</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.16.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 4c7fbad711..7ff9fd83eb 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -1159,6 +1159,11 @@ trans_fun([{put_map_exact,{f,Lbl},Map,Dst,_N,{list,Pairs}}|Instructions], Env) -
gen_put_map_instrs(new, exact, TempMapVar, Dst, new, Pairs, Env1)
end,
[MapMove, TempMapMove, PutInstructions | trans_fun(Instructions, Env2)];
+%%--- build_stacktrace ---
+trans_fun([build_stacktrace|Instructions], Env) ->
+ Vars = [mk_var({x,0})], %{x,0} is implict arg and dst
+ [hipe_icode:mk_primop(Vars,build_stacktrace,Vars),
+ trans_fun(Instructions, Env)];
%%--------------------------------------------------------------------
%%--- ERROR HANDLING ---
%%--------------------------------------------------------------------
diff --git a/lib/hipe/icode/hipe_icode_primops.erl b/lib/hipe/icode/hipe_icode_primops.erl
index ec9e3c8608..941516e8b1 100644
--- a/lib/hipe/icode/hipe_icode_primops.erl
+++ b/lib/hipe/icode/hipe_icode_primops.erl
@@ -132,6 +132,7 @@ is_safe({hipe_bs_primop, {bs_match_string, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_append, _, _, _, _}}) -> false;
is_safe({hipe_bs_primop, {bs_private_append, _, _}}) -> false;
is_safe({hipe_bs_primop, bs_init_writable}) -> true;
+is_safe(build_stacktrace) -> true;
is_safe(#mkfun{}) -> true;
is_safe(#unsafe_element{}) -> true;
is_safe(#unsafe_update_element{}) -> true;
@@ -234,6 +235,7 @@ fails({hipe_bs_primop, bs_final}) -> false;
fails({hipe_bs_primop, {bs_append, _, _, _, _}}) -> true;
fails({hipe_bs_primop, {bs_private_append, _, _}}) -> true;
fails({hipe_bs_primop, bs_init_writable}) -> true;
+fails(build_stacktrace) -> false;
fails(#mkfun{}) -> false;
fails(#unsafe_element{}) -> false;
fails(#unsafe_update_element{}) -> false;
@@ -731,6 +733,8 @@ type(Primop, Args) ->
erl_types:t_any();
debug_native_called ->
erl_types:t_any();
+ build_stacktrace ->
+ erl_types:t_list();
{M, F, A} ->
erl_bif_types:type(M, F, A, Args)
end.
@@ -903,6 +907,8 @@ type(Primop) ->
erl_types:t_any();
%%% -----------------------------------------------------
%%% Other
+ build_stacktrace ->
+ erl_types:t_any();
#closure_element{} ->
erl_types:t_any();
redtest ->
diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index 37360cee73..cf74c1eb5b 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -1186,7 +1186,8 @@ basic_type(unsafe_hd) -> not_analysed;
basic_type(unsafe_tl) -> not_int;
basic_type(#element{}) -> not_analysed;
basic_type(#unsafe_element{}) -> not_analysed;
-basic_type(#unsafe_update_element{}) -> not_analysed.
+basic_type(#unsafe_update_element{}) -> not_analysed;
+basic_type(build_stacktrace) -> not_int.
-spec analyse_bs_get_integer(integer(), integer(), boolean()) -> range_tuple().
diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src
index 66008a4178..1138d72dd2 100644
--- a/lib/hipe/main/hipe.app.src
+++ b/lib/hipe/main/hipe.app.src
@@ -237,4 +237,4 @@
{applications, [kernel,stdlib]},
{env, []},
{runtime_dependencies, ["syntax_tools-1.6.14","stdlib-3.4","kernel-5.3",
- "erts-9.2","compiler-5.0"]}]}.
+ "erts-9.3","compiler-5.0"]}]}.
diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
index 5b89d4946a..111dda3d82 100644
--- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl
+++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl
@@ -168,9 +168,13 @@ gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, SystemLimitLblName, ConstTab
bs_put_utf8 ->
[_Src, _Base, _Offset] = Args,
- NewDsts = get_real(Dst),
- [hipe_rtl:mk_call(NewDsts, bs_put_utf8, Args,
- TrueLblName, FalseLblName, not_remote)];
+ [NewOffs] = get_real(Dst),
+ RetLbl = hipe_rtl:mk_new_label(),
+ [hipe_rtl:mk_call([NewOffs], bs_put_utf8, Args,
+ hipe_rtl:label_name(RetLbl), [], not_remote),
+ RetLbl,
+ hipe_rtl:mk_branch(NewOffs, ne, hipe_rtl:mk_imm(0),
+ TrueLblName, FalseLblName, 0.99)];
bs_utf16_size ->
case Dst of
diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl
index 35ae2da895..d646b78a3d 100644
--- a/lib/hipe/rtl/hipe_rtl_primops.erl
+++ b/lib/hipe/rtl/hipe_rtl_primops.erl
@@ -394,6 +394,8 @@ gen_primop({Op,Dst,Args,Cont,Fail}, IsGuard, ConstTab) ->
end;
debug_native_called ->
[hipe_rtl:mk_call(Dst, Op, Args, Cont, Fail, not_remote)];
+ build_stacktrace ->
+ [hipe_rtl:mk_call(Dst, Op, Args, Cont, Fail, not_remote)];
%% Only names listed above are accepted! MFA:s are not primops!
_ ->
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index f88d9147b1..508ec00548 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.16.1
+HIPE_VSN = 3.17
diff --git a/lib/ic/doc/src/notes.xml b/lib/ic/doc/src/notes.xml
index ea8bf758cf..fc68ec386c 100644
--- a/lib/ic/doc/src/notes.xml
+++ b/lib/ic/doc/src/notes.xml
@@ -31,7 +31,22 @@
<file>notes.xml</file>
</header>
- <section><title>IC 4.4.2</title>
+ <section><title>IC 4.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>IC 4.4.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk
index f0e5e7c266..b9f1ef7f20 100644
--- a/lib/ic/vsn.mk
+++ b/lib/ic/vsn.mk
@@ -1 +1 @@
-IC_VSN = 4.4.2
+IC_VSN = 4.4.3
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 07e29b5542..70b2811c0e 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,7 +33,37 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 6.4.4</title>
+ <section><title>Inets 6.4.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ CGI environment variable CONTENT_LENGTH shall be a string</p>
+ <p>
+ Own Id: OTP-14679</p>
+ </item>
+ <item>
+ <p>
+ In relaxed mode disregard Content-Length header if there
+ is also a Transfer-Encoding header.</p>
+ <p>
+ Own Id: OTP-14727</p>
+ </item>
+ <item>
+ <p>
+ Eliminated race condition, that could cause http request
+ to sporadically fail to complete successfully, when
+ keep-alive connections are used.</p>
+ <p>
+ Own Id: OTP-14783</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.4.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/inets/test/Makefile b/lib/inets/test/Makefile
index ffc512050a..99a7e6a9db 100644
--- a/lib/inets/test/Makefile
+++ b/lib/inets/test/Makefile
@@ -150,6 +150,7 @@ INETS_ROOT = ../../inets
MODULES = \
inets_test_lib \
erl_make_certs \
+ make_certs \
ftp_SUITE \
ftp_format_SUITE \
http_format_SUITE \
@@ -157,10 +158,10 @@ MODULES = \
httpc_cookie_SUITE \
httpc_proxy_SUITE \
httpd_SUITE \
- old_httpd_SUITE \
+ httpd_bench_SUITE \
+ http_test_lib \
httpd_basic_SUITE \
httpd_mod \
- httpd_block \
httpd_load \
httpd_time_test \
httpd_1_1 \
@@ -189,7 +190,7 @@ SOURCE = $(ERL_FILES) $(HRL_FILES)
TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
-INETS_SPECS = inets.spec
+INETS_SPECS = inets.spec inets_bench.spec
COVER_FILE = inets.cover
INETS_FILES = inets.config $(INETS_SPECS)
@@ -200,8 +201,10 @@ INETS_FILES = inets.config $(INETS_SPECS)
# inets_ftp_suite \
# inets_tftp_suite
+
INETS_DATADIRS = inets_SUITE_data inets_socketwrap_SUITE_data
-HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data
+HTTPD_DATADIRS = httpd_test_data httpd_SUITE_data httpd_basic_SUITE_data old_httpd_SUITE_data httpd_bench_SUITE_data
+
HTTPC_DATADIRS = httpc_SUITE_data httpc_proxy_SUITE_data
FTP_DATADIRS = ftp_SUITE_data
diff --git a/lib/inets/test/http_test_lib.erl b/lib/inets/test/http_test_lib.erl
new file mode 100644
index 0000000000..38e9e4976e
--- /dev/null
+++ b/lib/inets/test/http_test_lib.erl
@@ -0,0 +1,180 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(http_test_lib).
+
+-include_lib("common_test/include/ct.hrl").
+-include("inets_test_lib.hrl").
+-include("http_internal.hrl").
+-include("httpc_internal.hrl").
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+dummy_server(SocketType, Inet, Extra) ->
+ dummy_server(self(), SocketType, Inet, Extra).
+
+dummy_server(Caller, SocketType, Inet, Extra) ->
+ Args = [Caller, SocketType, Inet, Extra],
+ Pid = spawn(?MODULE, dummy_server_init, Args),
+ receive
+ {port, Port} ->
+ {Pid, Port}
+ end.
+
+dummy_server_init(Caller, ip_comm, Inet, Extra) ->
+ ContentCb = proplists:get_value(content_cb, Extra),
+ BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}, {nodelay, true}],
+ Conf = proplists:get_value(conf, Extra),
+ {ok, ListenSocket} = gen_tcp:listen(0, [Inet | BaseOpts]),
+ {ok, Port} = inet:port(ListenSocket),
+ Caller ! {port, Port},
+ dummy_ipcomm_server_loop({httpd_request, parse, [[{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]},
+ [], ContentCb, Conf, ListenSocket);
+
+dummy_server_init(Caller, ssl, Inet, Extra) ->
+ ContentCb = proplists:get_value(content_cb, Extra),
+ SSLOptions = proplists:get_value(ssl, Extra),
+ Conf = proplists:get_value(conf, Extra),
+ BaseOpts = [binary, {reuseaddr,true}, {active, false}, {nodelay, true} |
+ SSLOptions],
+ dummy_ssl_server_init(Caller, BaseOpts, Inet, ContentCb, Conf).
+
+dummy_ssl_server_init(Caller, BaseOpts, Inet, ContentCb, Conf) ->
+ {ok, ListenSocket} = ssl:listen(0, [Inet | BaseOpts]),
+ {ok, {_, Port}} = ssl:sockname(ListenSocket),
+ Caller ! {port, Port},
+ dummy_ssl_server_loop({httpd_request, parse, [[{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]},
+ [], ContentCb, Conf, ListenSocket).
+
+dummy_ipcomm_server_loop(MFA, Handlers, ContentCb, Conf, ListenSocket) ->
+ receive
+ stop ->
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ {ok, Socket} = gen_tcp:accept(ListenSocket),
+ HandlerPid = dummy_request_handler(MFA, Socket, ContentCb, Conf),
+ gen_tcp:controlling_process(Socket, HandlerPid),
+ HandlerPid ! ipcomm_controller,
+ dummy_ipcomm_server_loop(MFA, [HandlerPid | Handlers],
+ ContentCb, Conf, ListenSocket)
+ end.
+
+dummy_ssl_server_loop(MFA, Handlers, ContentCb, Conf, ListenSocket) ->
+ receive
+ stop ->
+ lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
+ {stop, From} ->
+ Stopper = fun(Handler) -> Handler ! stop end,
+ lists:foreach(Stopper, Handlers),
+ From ! {stopped, self()}
+ after 0 ->
+ {ok, Socket} = ssl:transport_accept(ListenSocket),
+ HandlerPid = dummy_request_handler(MFA, Socket, ContentCb, Conf),
+ ssl:controlling_process(Socket, HandlerPid),
+ HandlerPid ! ssl_controller,
+ dummy_ssl_server_loop(MFA, [HandlerPid | Handlers],
+ ContentCb, Conf, ListenSocket)
+ end.
+
+dummy_request_handler(MFA, Socket, ContentCb, Conf) ->
+ spawn(?MODULE, dummy_request_handler_init, [MFA, Socket, ContentCb, Conf]).
+
+dummy_request_handler_init(MFA, Socket, ContentCb, Conf) ->
+ SockType =
+ receive
+ ipcomm_controller ->
+ inet:setopts(Socket, [{active, true}]),
+ ip_comm;
+ ssl_controller ->
+ ok = ssl:ssl_accept(Socket, infinity),
+ ssl:setopts(Socket, [{active, true}]),
+ ssl
+ end,
+ dummy_request_handler_loop(MFA, SockType, Socket, ContentCb, Conf).
+
+dummy_request_handler_loop({Module, Function, Args}, SockType, Socket, ContentCb, Conf) ->
+ receive
+ {Proto, _, Data} when (Proto =:= tcp) orelse (Proto =:= ssl) ->
+ case handle_request(Module, Function, [Data | Args], Socket, ContentCb, Conf) of
+ stop when Proto =:= tcp ->
+ gen_tcp:close(Socket);
+ stop when Proto =:= ssl ->
+ ssl:close(Socket);
+ NewMFA ->
+ dummy_request_handler_loop(NewMFA, SockType, Socket, ContentCb, Conf)
+ end;
+ stop when SockType =:= ip_comm ->
+ gen_tcp:close(Socket);
+ stop when SockType =:= ssl ->
+ ssl:close(Socket)
+ end.
+
+handle_request(Module, Function, Args, Socket, ContentCb, Conf) ->
+ case Module:Function(Args) of
+ {ok, Result} ->
+ case ContentCb:handle_http_msg(Result, Socket, Conf) of
+ stop ->
+ stop;
+ <<>> ->
+ {httpd_request, parse, [[{max_uri,?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]]};
+ Data ->
+ handle_request(httpd_request, parse,
+ [Data, [{max_uri, ?HTTP_MAX_URI_SIZE},
+ {max_header, ?HTTP_MAX_HEADER_SIZE},
+ {max_version,?HTTP_MAX_VERSION_STRING},
+ {max_method, ?HTTP_MAX_METHOD_STRING},
+ {max_content_length, ?HTTP_MAX_CONTENT_LENGTH},
+ {customize, httpd_custom}
+ ]], Socket, ContentCb, Conf)
+ end;
+ NewMFA ->
+ NewMFA
+ end.
+
+%% Perform a synchronous stop
+dummy_server_stop(Pid) ->
+ Pid ! {stop, self()},
+ receive
+ {stopped, Pid} ->
+ ok
+ end.
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 1e912e7640..0533b9ab70 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -1359,13 +1359,13 @@ group_name(Config) ->
server_start(sim_http, _) ->
Inet = inet_version(),
ok = httpc:set_options([{ipfamily, Inet}]),
- {_Pid, Port} = dummy_server(Inet),
+ {_Pid, Port} = http_test_lib:dummy_server(ip_comm, Inet, [{content_cb, ?MODULE}]),
Port;
server_start(sim_https, SslConfig) ->
Inet = inet_version(),
ok = httpc:set_options([{ipfamily, Inet}]),
- {_Pid, Port} = dummy_server(ssl, Inet, SslConfig),
+ {_Pid, Port} = http_test_lib:dummy_server(ssl, Inet, [{ssl, SslConfig}, {content_cb, ?MODULE}]),
Port;
server_start(_, HttpdConfig) ->
@@ -1469,13 +1469,7 @@ receive_replys([ID|IDs]) ->
ct:pal({recived_canceld_id, Other})
end.
-%% Perform a synchronous stop
-dummy_server_stop(Pid) ->
- Pid ! {stop, self()},
- receive
- {stopped, Pid} ->
- ok
- end.
+
inet_version() ->
inet. %% Just run inet for now
@@ -1603,7 +1597,7 @@ dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
handle_request(Module, Function, Args, Socket) ->
case Module:Function(Args) of
{ok, Result} ->
- case handle_http_msg(Result, Socket) of
+ case handle_http_msg(Result, Socket, []) of
stop ->
stop;
<<>> ->
@@ -1628,8 +1622,7 @@ handle_request(Module, Function, Args, Socket) ->
NewMFA
end.
-handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket) ->
-
+handle_http_msg({Method, RelUri, _, {_, Headers}, Body}, Socket, _) ->
ct:print("Request: ~p ~p", [Method, RelUri]),
NextRequest =
diff --git a/lib/inets/test/httpd_bench_SUITE.erl b/lib/inets/test/httpd_bench_SUITE.erl
new file mode 100644
index 0000000000..9d8cbf9ae2
--- /dev/null
+++ b/lib/inets/test/httpd_bench_SUITE.erl
@@ -0,0 +1,846 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+
+%%
+-module(httpd_bench_SUITE).
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-define(remote_host, "NETMARKS_REMOTE_HOST").
+-define(LF, [10]).
+-define(CR, [13]).
+-define(CRLF, ?CR ++ ?LF).
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+suite() ->
+ [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
+
+all() ->
+ [
+ {group, http_dummy},
+ {group, http_inets},
+ {group, http_nginx},
+ {group, https_inets},
+ {group, https_dummy},
+ {group, https_nginx},
+ {group, http_dummy_keep_alive},
+ {group, http_inets_keep_alive},
+ {group, http_nginx_keep_alive},
+ {group, https_inets_keep_alive},
+ {group, https_dummy_keep_alive},
+ {group, https_nginx_keep_alive}
+ ].
+
+groups() ->
+ [
+ {http_dummy, [], client_tests()},
+ {http_inets, [], client_tests()},
+ {http_nginx, [], client_tests()},
+ {https_dummy, [], client_tests()},
+ {https_inets, [], client_tests()},
+ {https_nginx, [], client_tests()},
+ {http_dummy_keep_alive, [], client_tests()},
+ {http_inets_keep_alive, [], client_tests()},
+ {http_nginx_keep_alive, [], client_tests()},
+ {https_dummy_keep_alive, [], client_tests()},
+ {https_inets_keep_alive, [], client_tests()},
+ {https_nginx_keep_alive, [], client_tests()}
+ ].
+
+
+client_tests() ->
+ [wget_small,
+ erl_dummy_small,
+ httpc_small,
+ wget_big,
+ erl_dummy_big,
+ httpc_big
+ ].
+
+init_per_suite(Config) ->
+ try
+ {Node, Host} = setup(Config, node()),
+ init_ssl(Config),
+ [{iter, 10}, {server_node, Node}, {server_host, Host} | Config]
+ catch _:_ ->
+ {skipped, "Benchmark machines only"}
+ end.
+
+end_per_suite(_Config) ->
+ [application:stop(App) || App <- [asn1, crypto, public_key, ssl, inets]].
+
+init_per_group(Group, Config) when Group == http_dummy_keep_alive;
+ Group == https_dummy_keep_alive;
+ Group == http_inets_keep_alive;
+ Group == https_inets_keep_alive;
+ Group == http_nginx_keep_alive;
+ Group == https_nginx_keep_alive ->
+ Version = http_version(Group),
+ start_web_server(Group,
+ [{keep_alive, true},
+ {reuse_sessions, false},
+ {http_version, Version},
+ {http_opts,[{version, Version}]},
+ {http_headers, [{"connection", "keep-alive"}]},
+ {httpc_opts, [{keep_alive_timeout, 1500},
+ {max_keep_alive_length, ?config(iter, Config)}]}
+ | Config]);
+init_per_group(Group, Config) when Group == http_dummy;
+ Group == https_dummy;
+ Group == http_inets;
+ Group == https_inets;
+ Group == http_nginx;
+ Group == https_nginx ->
+ Version = http_version(Group),
+ start_web_server(Group,
+ [{keep_alive, false},
+ {reuse_sessions, false},
+ {http_version, Version},
+ {http_headers, [{"connection", "close"}]},
+ {http_opts,[{version, Version}]},
+ {httpc_opts, [{keep_alive_timeout, 0}, {max_keep_alive_length, 0}]}
+ | Config]);
+
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(Group, Config) ->
+ stop_web_server(Group, Config).
+
+init_per_testcase(TestCase, Config) when TestCase == httpc_small;
+ TestCase == httpc_big
+ ->
+ Opts = ?config(httpc_opts, Config),
+ inets:start(httpc, [{profile, TestCase}, {socket_opts, [{nodelay, true}]}]),
+ httpc:set_options(Opts, TestCase),
+ [{profile, TestCase} | proplists:delete(profile, Config)];
+
+init_per_testcase(_, Config) ->
+ Config.
+end_per_testcase(TestCase, _Config) when TestCase == httpc_small;
+ TestCase == httpc_big ->
+ ok = inets:stop(httpc, TestCase);
+end_per_testcase(_TestCase, Config) ->
+ Config.
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+erl_dummy_small(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpd_lib_client, "1k_file", Config),
+ notify(Result, Config, "erl_1k_file").
+
+erl_dummy_big(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpd_lib_client, "1M_file", Config),
+ notify(Result, Config, "erl_1M_file").
+
+wget_small(Config) when is_list(Config) ->
+ {ok, Result} = run_test(wget_client, "1k_file", Config),
+ notify(Result, Config, "wget_1k_file").
+
+wget_big(Config) when is_list(Config) ->
+ {ok, Result} = run_test(wget_client, "1M_file", Config),
+ notify(Result, Config, "wget_1M_file").
+
+httpc_small(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpc_client, "1k_file", Config),
+ notify(Result, Config, "httpc_1k_file").
+
+httpc_big(Config) when is_list(Config) ->
+ {ok, Result} = run_test(httpc_client, "1M_file", Config),
+ notify(Result, Config, "httpc_1M_file").
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Report benchmark results ------------------------------------------------
+%%--------------------------------------------------------------------
+
+notify({TestPerSec, _MBps}, Config, Suffix) ->
+ Name = lists:concat([?config(protocol,Config), " ",
+ server_name(Config, [dummy_pid, httpd_pid, nginx_port]),
+ "", Suffix]),
+ ct:comment("~p tps", [TestPerSec]),
+ ct_event:notify(#event{name = benchmark_data,
+ data=[{value, TestPerSec},
+ {suite, ?MODULE},
+ {name, Name}]}),
+ ok.
+%%--------------------------------------------------------------------
+%% Setup erlang nodes ------------------------------------------------
+%%--------------------------------------------------------------------
+
+server_name(Config, [Server | Rest]) ->
+ case proplists:get_value(Server, Config) of
+ undefined ->
+ server_name(Config, Rest);
+ _ ->
+ server_name(Server)
+ end.
+
+server_name(httpd_pid) ->
+ "inets";
+server_name(nginx_port) ->
+ "nginx";
+server_name(dummy_pid) ->
+ "erlang".
+
+setup(_Config, nonode@nohost) ->
+ exit(dist_not_enabled);
+setup(_Config, _LocalNode) ->
+ Host = case os:getenv(?remote_host) of
+ false ->
+ {ok, This} = inet:gethostname(),
+ This;
+ RemHost ->
+ RemHost
+ end,
+ Node = list_to_atom("inets_perf_server@" ++ Host),
+ SlaveArgs = case init:get_argument(pa) of
+ {ok, PaPaths} ->
+ lists:append([" -pa " ++ P || [P] <- PaPaths]);
+ _ -> []
+ end,
+ Prog =
+ case os:find_executable("erl") of
+ false -> "erl";
+ P -> P
+ end,
+ case net_adm:ping(Node) of
+ pong -> ok;
+ pang ->
+ {ok, Node} = slave:start(Host, inets_perf_server, SlaveArgs, no_link, Prog)
+ end,
+ Path = code:get_path(),
+ true = rpc:call(Node, code, set_path, [Path]),
+ [ensure_started(Node, App) || App <- [asn1, crypto, public_key, ssl, inets]],
+ [ensure_started(node(), App) || App <- [asn1, crypto, public_key, ssl, inets]],
+ (Node =:= node()) andalso restrict_schedulers(client),
+ {Node, Host}.
+
+ensure_started(Node, App) ->
+ ok = rpc:call(Node, application, ensure_started, [App]).
+
+
+restrict_schedulers(Type) ->
+ %% We expect this to run on 8 core machine
+ Extra0 = 1,
+ Extra = if (Type =:= server) -> -Extra0; true -> Extra0 end,
+ Scheds = erlang:system_info(schedulers),
+ erlang:system_flag(schedulers_online, (Scheds div 2) + Extra).
+
+%%--------------------------------------------------------------------
+%% Setup TLS input files ------------------------------------------------
+%%--------------------------------------------------------------------
+
+init_ssl(Config) ->
+ DDir = ?config(data_dir, Config),
+ PDir = ?config(priv_dir, Config),
+ {ok, _} = make_certs:all(DDir,
+ PDir).
+cert_opts(Config) ->
+ ClientCaCertFile = filename:join([?config(priv_dir, Config),
+ "client", "cacerts.pem"]),
+ ClientCertFile = filename:join([?config(priv_dir, Config),
+ "client", "cert.pem"]),
+ ServerCaCertFile = filename:join([?config(priv_dir, Config),
+ "server", "cacerts.pem"]),
+ ServerCertFile = filename:join([?config(priv_dir, Config),
+ "server", "cert.pem"]),
+ ServerKeyFile = filename:join([?config(priv_dir, Config),
+ "server", "key.pem"]),
+ ClientKeyFile = filename:join([?config(priv_dir, Config),
+ "client", "key.pem"]),
+ [{server_verification_opts, [{reuseaddr, true},
+ {cacertfile, ServerCaCertFile},
+ {ciphers, ["ECDHE-RSA-AES256-GCM-SHA384"]},
+ {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
+ {client_verification_opts, [
+ %%{verify, verify_peer},
+ {cacertfile, ClientCaCertFile},
+ {certfile, ClientCertFile},
+ {keyfile, ClientKeyFile}]}].
+
+%%--------------------------------------------------------------------
+%% Run clients ------------------------------------------------
+%%--------------------------------------------------------------------
+
+run_test(Client, File, Config) ->
+ Parent = self(),
+ Pid = spawn(fun() ->
+ receive
+ go ->
+ Parent ! {self(),
+ do_runs(Client, [{file, File} | Config])}
+ end
+ end),
+ Pid ! go,
+ receive
+ {Pid,{{tps, Tps}, {mbps, MBps}}} ->
+ ct:pal("Tps: ~p Bps~p", [Tps, MBps]),
+ {ok, {Tps, MBps}}
+ end.
+
+do_runs(Client, Config) ->
+ N = ?config(iter, Config),
+ DataDir = ?config(data_dir, Config),
+ File = ?config(file, Config),
+ Name = filename:join(DataDir, File),
+ Args = ?MODULE:Client(Config),
+ ?MODULE:Client({init, Args}),
+ Run =
+ fun() ->
+ ok = ?MODULE:Client(Args, N)
+ end,
+ {ok, Info} = file:read_file_info(Name, []),
+ Length = Info#file_info.size,
+ {TimeInMicro, _} = timer:tc(Run),
+ ReqPerSecond = (1000000 * N) div TimeInMicro,
+ BytesPerSecond = (1000000 * N * Length) div TimeInMicro,
+ {{tps, ReqPerSecond}, {mbps, BytesPerSecond}}.
+
+
+httpc_client({init, [_, Profile, URL, Headers, HTTPOpts]}) ->
+ %% Make sure pipelining feature will kick in when appropriate.
+ {ok, {{_ ,200, "OK"}, _,_}} = httpc:request(get,{URL, Headers}, HTTPOpts,
+ [{body_format, binary},
+ {socket_opts, [{nodelay, true}]}], Profile),
+ ct:sleep(1000);
+httpc_client(Config) ->
+ File = ?config(file, Config),
+ Protocol = ?config(protocol, Config),
+ Profile = ?config(profile, Config),
+ URL = (?config(urlfun,Config))(File),
+ Headers = ?config(http_headers, Config),
+ HTTPOpts = ?config(http_opts, Config),
+ [Protocol, Profile, URL, Headers, HTTPOpts].
+httpc_client(_,0) ->
+ ok;
+httpc_client([Protocol, Profile, URL, Headers, HTTPOpts], N) ->
+ {ok, {{_ ,200,"OK"}, _,_}} = httpc:request(get,{URL, Headers}, HTTPOpts, [{body_format, binary},
+ {socket_opts, [{nodelay, true}]}], Profile),
+ httpc_client([Protocol, Profile, URL, Headers, HTTPOpts], N-1).
+
+httpd_lib_client({init, [_, Type, Version, Request, Host, Port, Opts]}) ->
+ ok = httpd_test_lib:verify_request(Type, Host,
+ Port,
+ Opts, node(),
+ Request,
+ [{statuscode, 200},
+ {version, Version}], infinity),
+ ct:sleep(1000);
+httpd_lib_client(Config) ->
+ File = ?config(file, Config),
+ KeepAlive = ?config(keep_alive, Config),
+ Host = ?config(server_host, Config),
+ Port = ?config(port, Config),
+ ReuseSession = ?config(reuse_sessions, Config),
+ {Type, Opts} =
+ case ?config(protocol, Config) of
+ "http" ->
+ {ip_comm, [{active, true}, {mode, binary},{nodelay, true}]};
+ "https" ->
+ SSLOpts = proplists:get_value(client_verification_opts, cert_opts(Config)),
+ {ssl, [{active, true}, {mode, binary}, {nodelay, true},
+ {reuse_sessions, ReuseSession} | SSLOpts]}
+
+ end,
+ Version = ?config(http_version, Config),
+ Request = case KeepAlive of
+ true ->
+ http_request("GET /" ++ File ++ " ", Version, Host, {"connection:keep-alive\r\n", ""});
+ false ->
+ http_request("GET /" ++ File ++ " ", Version, Host)
+ end,
+
+ Args = [KeepAlive, Type, Version, Request, Host, Port, Opts],
+ httpd_lib_client(Args, 1),
+ Args.
+
+httpd_lib_client(_, 0) ->
+ ok;
+httpd_lib_client([true, Type, Version, Request, Host, Port, Opts], N) ->
+ ok = httpd_test_lib:verify_request_N(Type, Host,
+ Port,
+ Opts, node(),
+ Request,
+ [{statuscode, 200},
+ {version, Version}], infinity, N);
+httpd_lib_client([false, Type, Version, Request, Host, Port, Opts] = List, N) ->
+ ok = httpd_test_lib:verify_request(Type, Host,
+ Port,
+ Opts, node(),
+ Request,
+ [{statuscode, 200},
+ {version, Version}], infinity),
+ httpd_lib_client(List, N-1).
+
+wget_client({init,_}) ->
+ ok;
+wget_client(Config) ->
+ File = ?config(file, Config),
+ URL = (?config(urlfun,Config))(File),
+ KeepAlive = ?config(keep_alive, Config),
+ PrivDir = ?config(priv_dir, Config),
+ Protocol = ?config(protocol, Config),
+ Iter = ?config(iter, Config),
+ FileName = filename:join(PrivDir, "wget_req"),
+ ProtocolOpts = case Protocol of
+ "http" ->
+ [];
+ "https" ->
+ proplists:get_value(client_verification_opts, cert_opts(Config))
+ end,
+ wget_req_file(FileName,URL,Iter),
+ [KeepAlive, FileName, URL, Protocol, ProtocolOpts, Iter].
+wget_client([KeepAlive, WgetFile, _URL, Protocol, ProtocolOpts, _], _) ->
+ process_flag(trap_exit, true),
+ Cmd = wget_N(KeepAlive, WgetFile, Protocol, ProtocolOpts),
+ %%ct:pal("Wget cmd: ~p", [Cmd]),
+ Port = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ wait_for_wget(Port).
+
+
+%%--------------------------------------------------------------------
+%% Start/stop servers ------------------------------------------------
+%%--------------------------------------------------------------------
+start_web_server(Group, Config) when Group == http_dummy;
+ Group == http_dummy_keep_alive ->
+ start_dummy("http", Config);
+
+start_web_server(Group, Config) when Group == https_dummy;
+ Group == https_dummy_keep_alive ->
+ start_dummy("https", Config);
+
+start_web_server(Group, Config) when Group == http_inets;
+ Group == http_inets_keep_alive ->
+ start_inets("http", [], Config);
+
+start_web_server(Group, Config) when Group == https_inets;
+ Group == https_inets_keep_alive ->
+ Opts = proplists:get_value(server_verification_opts, cert_opts(Config)),
+ ReuseSessions = ?config(reuse_sessions, Config),
+ SSLConfHttpd = [{socket_type, {essl,
+ [{nodelay, true}, {reuse_sessions, ReuseSessions} | Opts]}}],
+ start_inets("https", SSLConfHttpd, Config);
+
+start_web_server(Group, Config) when Group == http_nginx;
+ Group == http_nginx_keep_alive ->
+ case os:find_executable("nginx") of
+ false ->
+ {skip, "nginx not found"};
+ _ ->
+ start_nginx("http", Config)
+ end;
+
+start_web_server(Group, Config) when Group == https_nginx;
+ Group == https_nginx_keep_alive ->
+ case os:find_executable("nginx") of
+ false ->
+ {skip, "nginx not found"};
+ _ ->
+ start_nginx("https", cert_opts(Config) ++ Config)
+ end.
+
+start_inets(Protocol, ConfHttpd, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Node = ?config(server_node, Config),
+ Host = ?config(server_host, Config),
+ HTTPVersion = ?config(http_version, Config),
+ Conf = [httpd, [{port,0},
+ {http_version, HTTPVersion},
+ {ipfamily, inet},
+ {server_name, "inets_test"},
+ {server_root, PrivDir},
+ {document_root, DataDir},
+ {keep_alive, ?config(keep_alive, Config)},
+ {keep_alive_timeout, 360}
+ | ConfHttpd]],
+ {ok, Pid} = rpc:call(Node, inets, start, Conf),
+ Port = proplists:get_value(port, rpc:call(Node, httpd, info, [Pid])),
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+ [{httpd_pid,Pid},{urlfun,F},{protocol,Protocol},{port,Port} | Config].
+
+start_dummy("http"= Protocol, Config) ->
+ HTTPVersion = ?config(http_version, Config),
+ Node = ?config(server_node, Config),
+ %%DataDir= ?config(data_dir, Config),
+ Host = ?config(server_host, Config),
+ Conf = [
+ %%{big, filename:join(DataDir, "1M_file")},
+ %%{small, filename:join(DataDir, "1k_file")},
+ {big, {gen, crypto:rand_bytes(1000000)}},
+ {small, {gen, crypto:rand_bytes(1000)}},
+ {http_version, HTTPVersion},
+ {keep_alive, ?config(keep_alive, Config)}
+ ],
+ {Pid, Port} = rpc:call(Node, http_test_lib, dummy_server, [ip_comm, inet, [{content_cb, ?MODULE}, {conf, Conf}]]),
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+ [{dummy_pid,Pid},{urlfun,F},{protocol, Protocol},{port,Port} | Config];
+
+start_dummy("https" = Protocol, Config) ->
+ HTTPVersion = ?config(http_version, Config),
+ Node = ?config(server_node, Config),
+ %% DataDir= ?config(data_dir, Config),
+ Host = ?config(server_host, Config),
+ SSLOpts = proplists:get_value(server_verification_opts, cert_opts(Config)),
+ Opts = [{active, true}, {nodelay, true}, {reuseaddr, true} | SSLOpts],
+ Conf = [%%{big, filename:join(DataDir, "1M_file")},
+ %%{small, filename:join(DataDir, "1k_file")},
+ {big, {gen, crypto:rand_bytes(1000000)}},
+ {small, {gen, crypto:rand_bytes(1000)}},
+ {http_version, HTTPVersion},
+ {keep_alive, ?config(keep_alive, Config)}
+ ],
+ {Pid, Port} = rpc:call(Node, http_test_lib, dummy_server,
+ [ssl, inet, [{ssl, Opts}, {content_cb, ?MODULE}, {conf, Conf}]]),
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+ [{dummy_pid,Pid},{urlfun,F},{protocol,Protocol},{port,Port} | Config].
+
+start_nginx(Protocol, Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Host = ?config(server_host, Config),
+ Port = inet_port(node()),
+
+ ConfFile = filename:join(PrivDir, "nginx.conf"),
+ nginx_conf(ConfFile, [{port, Port}, {protocol, Protocol} | Config]),
+ Cmd = "nginx -c " ++ ConfFile,
+ NginxPort = open_port({spawn, Cmd}, [{cd, DataDir}, stderr_to_stdout]),
+
+ F = fun(File) ->
+ lists:concat([Protocol,"://",Host,":",Port,"/",File])
+ end,
+
+ wait_for_nginx_up(Host, Port),
+
+ [{port, Port},{nginx_port, NginxPort},{urlfun,F},{protocol, Protocol} | Config ].
+
+stop_nginx(Config)->
+ PrivDir = ?config(priv_dir, Config),
+ {ok, Bin} = file:read_file(filename:join(PrivDir, "nginx.pid")),
+ Pid = string:strip(binary_to_list(Bin), right, $\n),
+ Cmd = "kill " ++ Pid,
+ os:cmd(Cmd).
+
+stop_web_server(Group, Config) when Group == http_inets;
+ Group == http_inets_keep_alive;
+ Group == https_inets;
+ Group == https_inets_keep_alive ->
+ ServerNode = ?config(server_node, Config),
+ rpc:call(ServerNode, inets, stop, [httpd, ?config(httpd_pid, Config)]);
+stop_web_server(Group, Config) when Group == http_dummy;
+ Group == http_dummy_keep_alive;
+ Group == https_dummy;
+ Group == https_dummy_keep_alive ->
+ stop_dummy_server(Config);
+stop_web_server(Group, Config) when Group == http_nginx;
+ Group == http_nginx_keep_alive;
+ Group == https_nginx;
+ Group == https_nginx_keep_alive ->
+ stop_nginx(Config).
+
+stop_dummy_server(Config) ->
+ case ?config(dummy_pid, Config) of
+ Pid when is_pid(Pid) ->
+ exit(Pid, kill);
+ _ ->
+ ok
+ end.
+
+%%--------------------------------------------------------------------
+%% Misc ------------------------------------------------
+%%--------------------------------------------------------------------
+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".
+
+http_version(_) ->
+ "HTTP/1.1".
+
+inet_port(Node) ->
+ {Port, Socket} = do_inet_port(Node),
+ rpc:call(Node, gen_tcp, close, [Socket]),
+ Port.
+
+do_inet_port(Node) ->
+ {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
+ {ok, Port} = rpc:call(Node, inet, port, [Socket]),
+ {Port, Socket}.
+
+%%--------------------------------------------------------------------
+%% Dummy server callbacks ------------------------------------------------
+%%--------------------------------------------------------------------
+
+handle_request(CB, S, "/1M_file" ++ _, Opts) ->
+ Name = proplists:get_value(big, Opts),
+ KeepAlive = proplists:get_value(keep_alive, Opts),
+ do_handle_request(CB, S, Name, Opts, KeepAlive);
+handle_request(CB, S, "/1k_file" ++ _, Opts) ->
+ Name = proplists:get_value(small, Opts),
+ KeepAlive = proplists:get_value(keep_alive, Opts),
+ do_handle_request(CB, S, Name, Opts, KeepAlive).
+
+do_handle_request(CB, S, Name, Opts, KeepAlive) when is_list(Name) ->
+ Version = proplists:get_value(http_version, Opts),
+ {ok, Fdesc} = file:open(Name, [read, binary]),
+ {ok, Info} = file:read_file_info(Name, []),
+ Length = Info#file_info.size,
+ Response = response_status_line_and_headers(Version, "Content-Length:"
+ ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
+ CB:send(S, Response),
+ send_file(CB, S, Fdesc);
+do_handle_request(CB, S, {gen, Data}, Opts, KeepAlive) ->
+ Version = proplists:get_value(http_version, Opts),
+ Length = size(Data),
+ Response = response_status_line_and_headers(Version, "Content-Length:"
+ ++ integer_to_list(Length) ++ ?CRLF, keep_alive(KeepAlive)),
+ CB:send(S, Response),
+ send_file(CB, S, {gen, Data}).
+
+send_file(CB, S, {gen, Data}) ->
+ CB:send(S, Data);
+ %% ChunkSize = 64*1024,
+ %% case size(Data) of
+ %% N when N > ChunkSize ->
+ %% <<Chunk:N/binary, Rest/binary>> = Data,
+ %% %%{Chunk, Rest} = lists:split(N, Data),
+ %% CB:send(S, Chunk),
+ %% send_file(CB, S, {gen, Rest});
+ %% _ ->
+ %% CB:send(S, Data)
+ %% end;
+
+send_file(CB, S, FileDesc) ->
+ case file:read(FileDesc, 64*1024) of
+ {ok, Chunk} ->
+ CB:send(S, Chunk),
+ send_file(CB, S, FileDesc);
+ eof ->
+ file:close(FileDesc),
+ ok
+ end.
+
+response_status_line_and_headers(Version, Headers, ConnectionHeader) ->
+ StatusLine = [Version, " ", "200 OK", ?CRLF],
+ [StatusLine, Headers, ConnectionHeader, ?CRLF].
+
+keep_alive(true)->
+ "Connection:keep-alive\r\n";
+keep_alive(false) ->
+ "Connection:close\r\n".
+
+handle_http_msg({_Method, RelUri, _, {_, _Headers}, _Body}, Socket, Conf) ->
+ handle_request(connect_cb(Socket), Socket, RelUri, Conf),
+ case proplists:get_value(keep_alive, Conf) of
+ true ->
+ <<>>;
+ false ->
+ stop
+ end.
+
+connect_cb({sslsocket, _, _}) ->
+ ssl;
+connect_cb(_) ->
+ gen_tcp.
+
+%%--------------------------------------------------------------------
+%% Setup wget ------------------------------------------------
+%%--------------------------------------------------------------------
+wget_req_file(FileName, Url, Iter) ->
+ {ok, File} = file:open(FileName, [write]),
+ write_urls(File, Url, Iter).
+
+write_urls(File, Url, 1) ->
+ file:write(File, Url),
+ file:close(File);
+write_urls(File, Url, N) ->
+ file:write(File, Url),
+ file:write(File, "\n"),
+ write_urls(File, Url, N-1).
+
+wait_for_wget(Port) ->
+ receive
+ {Port, {data, _Data}} when is_port(Port) ->
+ wait_for_wget(Port);
+ {Port, closed} ->
+ ok;
+ {'EXIT', Port, _Reason} ->
+ ok
+ end.
+
+wget_N(KeepAlive, WegetFile, "http", _ProtocolOpts) ->
+ "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive) ++
+ " --no-cache --timeout=120" ;
+wget_N(KeepAlive, WegetFile, "https", ProtocolOpts) ->
+
+ "wget -i " ++ WegetFile ++ " " ++ wget_keep_alive(KeepAlive)
+ ++ wget_cert(ProtocolOpts) ++ wget_key(ProtocolOpts)
+ ++ wget_cacert(ProtocolOpts) ++
+ " --no-cache --timeout=120".
+
+wget(KeepAlive, URL, "http", _ProtocolOpts) ->
+ "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive) ++
+ " --no-cache --timeout=120" ;
+wget(KeepAlive, URL, "https", ProtocolOpts) ->
+
+ "wget " ++ URL ++ " " ++ wget_keep_alive(KeepAlive)
+ ++ wget_cert(ProtocolOpts) ++ wget_key(ProtocolOpts)
+ ++ wget_cacert(ProtocolOpts) ++
+ " --no-cache --timeout=120".
+
+wget_keep_alive(true)->
+ "";
+wget_keep_alive(false) ->
+ "--no-http-keep-alive ".
+
+wget_cacert(ProtocolOpts) ->
+ "--ca-certificate=" ++ proplists:get_value(cacertfile, ProtocolOpts) ++ " ".
+
+wget_cert(ProtocolOpts) ->
+ "--certificate=" ++ proplists:get_value(certfile, ProtocolOpts) ++ " ".
+
+wget_key(ProtocolOpts) ->
+ "--private-key=" ++ proplists:get_value(keyfile, ProtocolOpts) ++ " ".
+
+%%--------------------------------------------------------------------
+%% Setup nginx ------------------------------------------------
+%%--------------------------------------------------------------------
+nginx_conf(ConfFile, Config)->
+ Protocol = ?config(protocol, Config),
+ file:write_file(ConfFile,
+ [format_nginx_conf(nginx_global(Config)),
+ format_nginx_conf(nginx_events(Config)),
+ format_nginx_conf(nginx_http(Protocol, Config))]).
+
+format_nginx_conf(Directives) ->
+ lists:map(fun({Key, Value}) ->
+ io_lib:format("~s ~s;\n", [Key, Value]);
+ (Str) ->
+ Str
+ end, Directives).
+
+
+nginx_global(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ [{"pid", filename:join(PrivDir, "nginx.pid")},
+ {"error_log", filename:join(PrivDir, "nginx.pid")},
+ {"worker_processes", "1"}].
+
+nginx_events(_Config) ->
+ ["events {\n",
+ {"worker_connections", "1024"},
+ "\n}"
+ ].
+
+nginx_http("http", Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(port, Config),
+ ["http {\n" |
+ nginx_defaults(PrivDir) ++
+ [" server {",
+ {root, DataDir},
+ {listen, integer_to_list(Port)},
+ " location / {\n try_files $uri $uri/ /index.html;\n}"
+ "}\n", "}\n"
+ ]
+ ];
+
+nginx_http("https", Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ DataDir = ?config(data_dir, Config),
+ Port = ?config(port, Config),
+ SSLOpts = ?config(server_verification_opts, Config),
+ Ciphers = proplists:get_value(ciphers, SSLOpts),
+ ReuseSession = ?config(reuse_sessions, Config),
+ ["http {" |
+ nginx_defaults(PrivDir) ++
+ [" server {",
+ {"root", DataDir},
+ {"listen", integer_to_list(Port) ++ " ssl"},
+ {"ssl_certificate", ?config(certfile, SSLOpts)},
+ {"ssl_certificate_key", ?config(keyfile, SSLOpts)},
+ {"ssl_protocols", "TLSv1 TLSv1.1 TLSv1.2"},
+ {"ssl_ciphers", Ciphers},
+ {"ssl_session_cache", nginx_reuse_session(ReuseSession)},
+ " location / {\n try_files $uri $uri/ /index.html;\n}"
+ "}\n", "}\n"
+ ]
+ ].
+
+nginx_defaults(PrivDir) ->
+ [
+ %% Set temp and cache file options that will otherwise default to
+ %% restricted locations accessible only to root.
+ {"client_body_temp_path", filename:join(PrivDir, "client_body")},
+ {"fastcgi_temp_path", filename:join(PrivDir, "fastcgi_temp")},
+ {"proxy_temp_path", filename:join(PrivDir, "proxy_temp")},
+ {"scgi_temp_path", filename:join(PrivDir, "scgi_temp")},
+ {"uwsgi_temp_path", filename:join(PrivDir, "uwsgi_temp_path")},
+ {"access_log", filename:join(PrivDir, "access.log")},
+ {"error_log", filename:join(PrivDir, "error.log")},
+ %% Standard options
+ {"sendfile", "on"},
+ {"tcp_nopush", "on"},
+ {"tcp_nodelay", "on"},
+ {"keepalive_timeout", "360"},
+ {"types_hash_max_size", "2048"},
+ {"include", "/etc/nginx/mime.types"},
+ {"default_type", "application/octet-stream"}
+ ].
+
+nginx_reuse_session(true) ->
+ "on";
+nginx_reuse_session(false) ->
+ "off".
+
+wait_for_nginx_up(Host, Port) ->
+ case gen_tcp:connect(Host, Port, []) of
+ {ok, Socket} ->
+ gen_tcp:close(Socket);
+ _ ->
+ ct:sleep(100),
+ wait_for_nginx_up(Host, Port)
+ end.
+
diff --git a/lib/inets/test/httpd_bench_SUITE_data/1M_file b/lib/inets/test/httpd_bench_SUITE_data/1M_file
new file mode 100644
index 0000000000..557989144e
--- /dev/null
+++ b/lib/inets/test/httpd_bench_SUITE_data/1M_file
Binary files differ
diff --git a/lib/inets/test/httpd_bench_SUITE_data/1k_file b/lib/inets/test/httpd_bench_SUITE_data/1k_file
new file mode 100644
index 0000000000..cade172d80
--- /dev/null
+++ b/lib/inets/test/httpd_bench_SUITE_data/1k_file
Binary files differ
diff --git a/lib/inets/test/httpd_block.erl b/lib/inets/test/httpd_block.erl
deleted file mode 100644
index 45547e6d4e..0000000000
--- a/lib/inets/test/httpd_block.erl
+++ /dev/null
@@ -1,372 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
--module(httpd_block).
-
--include_lib("common_test/include/ct.hrl").
-
-%% General testcases bodies called from httpd_SUITE
--export([block_disturbing_idle/4, block_non_disturbing_idle/4,
- block_503/4, block_disturbing_active/4,
- block_non_disturbing_active/4,
- block_disturbing_active_timeout_not_released/4,
- block_disturbing_active_timeout_released/4,
- block_non_disturbing_active_timeout_not_released/4,
- block_non_disturbing_active_timeout_released/4,
- disturbing_blocker_dies/4,
- non_disturbing_blocker_dies/4, restart_no_block/4,
- restart_disturbing_block/4, restart_non_disturbing_block/4
- ]).
-
-%% Help functions
--export([httpd_block/3, httpd_block/4, httpd_unblock/2, httpd_restart/2]).
--export([do_block_server/4, do_block_nd_server/5, do_long_poll/6]).
-
--define(report(Label, Content),
- inets:report_event(20, Label, test_case,
- [{module, ?MODULE}, {line, ?LINE} | Content])).
-
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-block_disturbing_idle(_Type, Port, Host, Node) ->
- io:format("block_disturbing_idle -> entry~n", []),
- validate_admin_state(Node, Host, Port, unblocked),
- block_server(Node, Host, Port),
- validate_admin_state(Node, Host, Port, blocked),
- unblock_server(Node, Host, Port),
- validate_admin_state(Node, Host, Port, unblocked),
- io:format("block_disturbing_idle -> done~n", []),
- ok.
-
-%%--------------------------------------------------------------------
-block_non_disturbing_idle(_Type, Port, Host, Node) ->
- unblocked = get_admin_state(Node, Host, Port),
- block_nd_server(Node, Host, Port),
- blocked = get_admin_state(Node, Host, Port),
- unblock_server(Node, Host, Port),
- unblocked = get_admin_state(Node, Host, Port),
- ok.
-
-%%--------------------------------------------------------------------
-block_503(Type, Port, Host, Node) ->
- Req = "GET / HTTP/1.0\r\ndummy-host.ericsson.se:\r\n\r\n",
- unblocked = get_admin_state(Node, Host, Port),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, 200},
- {version, "HTTP/1.0"}]),
- ok = block_server(Node, Host, Port),
- blocked = get_admin_state(Node, Host, Port),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, 503},
- {version, "HTTP/1.0"}]),
- ok = unblock_server(Node, Host, Port),
- unblocked = get_admin_state(Node, Host, Port),
- ok = httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, 200},
- {version, "HTTP/1.0"}]).
-
-%%--------------------------------------------------------------------
-block_disturbing_active(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Pid = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(15000),
- block_server(Node, Host, Port),
- await_suite_failed_process_exit(Pid, "poller", 60000,
- connection_closed),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_non_disturbing_active(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(15000),
- ok = block_nd_server(Node, Host, Port),
- await_normal_process_exit(Poller, "poller", 60000),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(15000),
- ok = httpd_block(undefined, Port, disturbing, 50000),
- await_normal_process_exit(Poller, "poller", 30000),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_disturbing_active_timeout_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 40000),
- ct:sleep(5000),
- ok = httpd_block(undefined, Port, disturbing, 10000),
- await_suite_failed_process_exit(Poller, "poller", 40000,
- connection_closed),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-block_non_disturbing_active_timeout_not_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(5000),
- ok = block_nd_server(Node, Host, Port, 40000),
- await_normal_process_exit(Poller, "poller", 60000),
- blocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-block_non_disturbing_active_timeout_released(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 45000),
- 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),
- unblocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-disturbing_blocker_dies(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(5000),
- Blocker = blocker(Node, Host, Port, 10000),
- ct:sleep(5000),
- exit(Blocker,simulate_blocker_crash),
- await_normal_process_exit(Poller, "poller", 60000),
- unblocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-
-%%--------------------------------------------------------------------
-non_disturbing_blocker_dies(Type, Port, Host, Node) ->
- process_flag(trap_exit, true),
- Poller = long_poll(Type, Host, Port, Node, 200, 60000),
- ct:sleep(5000),
- Blocker = blocker_nd(Node, Host, Port, 10000, ok),
- ct:sleep(5000),
- exit(Blocker, simulate_blocker_crash),
- await_normal_process_exit(Poller, "poller", 60000),
- unblocked = get_admin_state(Node, Host, Port),
- process_flag(trap_exit, false),
- ok.
-%%--------------------------------------------------------------------
-restart_no_block(_, Port, Host, Node) ->
- {error,_Reason} = restart_server(Node, Host, Port).
-
-%%--------------------------------------------------------------------
-restart_disturbing_block(_, Port, Host, Node) ->
- ?report("restart_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port),
- ?report("restart_disturbing_block - block_server", []),
- ok = block_server(Node, Host, Port),
- ?report("restart_disturbing_block - restart_server", []),
- ok = restart_server(Node, Host, Port),
- ?report("restart_disturbing_block - unblock_server", []),
- ok = unblock_server(Node, Host, Port),
- ?report("restart_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port).
-
-%%--------------------------------------------------------------------
-restart_non_disturbing_block(_, Port, Host, Node) ->
- ?report("restart_non_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port),
- ?report("restart_non_disturbing_block - block_nd_server", []),
- ok = block_nd_server(Node, Host, Port),
- ?report("restart_non_disturbing_block - restart_server", []),
- ok = restart_server(Node, Host, Port),
- ?report("restart_non_disturbing_block - unblock_server", []),
- ok = unblock_server(Node, Host, Port),
- ?report("restart_non_disturbing_block - get_admin_state (unblocked)", []),
- unblocked = get_admin_state(Node, Host, Port).
-
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-blocker(Node, Host, Port, Timeout) ->
- spawn_link(?MODULE, do_block_server,[Node, Host, Port,Timeout]).
-
-do_block_server(Node, Host, Port, Timeout) ->
- ok = block_server(Node, Host, Port, Timeout),
- exit(normal).
-
-blocker_nd(Node, Host, Port, Timeout, Reply) ->
- spawn_link(?MODULE, do_block_nd_server,
- [Node, Host, Port, Timeout, Reply]).
-
-do_block_nd_server(Node, Host, Port, Timeout, Reply) ->
- Reply = block_nd_server(Node, Host, Port, Timeout),
- exit(normal).
-
-restart_server(Node, _Host, Port) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_restart, [Addr, Port]).
-
-
-block_server(Node, _Host, Port) ->
- io:format("block_server -> entry~n", []),
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, disturbing]).
-
-
-block_server(Node, _Host, Port, Timeout) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, disturbing, Timeout]).
-
-
-block_nd_server(Node, _Host, Port) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, non_disturbing]).
-
-block_nd_server(Node, _Host, Port, Timeout) ->
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_block, [Addr, Port, non_disturbing, Timeout]).
-
-unblock_server(Node, _Host, Port) ->
- io:format("~p:~p:block_server -> entry~n", [node(),self()]),
- Addr = undefined,
- rpc:call(Node, ?MODULE, httpd_unblock, [Addr, Port]).
-
-
-httpd_block(Addr, Port, Mode) ->
- io:format("~p:~p:httpd_block -> entry~n", [node(),self()]),
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:block(Pid, Mode);
- _ ->
- {error, not_started}
- end.
-
-httpd_block(Addr, Port, Mode, Timeout) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:block(Pid, Mode, Timeout);
- _ ->
- {error, not_started}
- end.
-
-httpd_unblock(Addr, Port) ->
- io:format("~p:~p:httpd_unblock -> entry~n", [node(),self()]),
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:unblock(Pid);
- _ ->
- {error, not_started}
- end.
-
-httpd_restart(Addr, Port) ->
- Name = make_name(Addr, Port),
- case whereis(Name) of
- Pid when is_pid(Pid) ->
- httpd_manager:reload(Pid, undefined);
- _ ->
- {error, not_started}
- end.
-
-make_name(Addr, Port) ->
- httpd_util:make_name("httpd", Addr, Port, default).
-
-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]),
- case get_admin_state(Node, Host, Port) of
- Expect ->
- ok;
- Unexpected ->
- io:format("failed validating server admin state: ~p~n",
- [Unexpected]),
- exit({unexpected_admin_state, Unexpected, Expect})
- end.
-
-
-await_normal_process_exit(Pid, Name, Timeout) ->
- receive
- {'EXIT', Pid, normal} ->
- ok;
- {'EXIT', Pid, Reason} ->
- Err =
- lists:flatten(
- io_lib:format("expected normal exit, "
- "unexpected exit of ~s process: ~p",
- [Name, Reason])),
- ct:fail(Err)
- after Timeout ->
- ct:fail("timeout while waiting for " ++ Name)
- end.
-
-
-await_suite_failed_process_exit(Pid, Name, Timeout, Why) ->
- receive
- {'EXIT', Pid, {test_failed, Why}} ->
- ok;
- {'EXIT', Pid, Reason} ->
- Err =
- lists:flatten(
- io_lib:format("expected connection_closed, "
- "unexpected exit of ~s process: ~p",
- [Name, Reason])),
- ct:fail(Err)
- after Timeout ->
- ct:fail("timeout while waiting for " ++ Name)
- end.
-
-long_poll(Type, Host, Port, Node, StatusCode, Timeout) ->
- spawn_link(?MODULE, do_long_poll, [Type, Host, Port, Node,
- StatusCode, Timeout]).
-
-do_long_poll(Type, Host, Port, Node, StatusCode, Timeout) ->
- Mod = "httpd_example",
- Func = "delay",
- Req = lists:flatten(io_lib:format("GET /eval?" ++ Mod ++ ":" ++ Func ++
- "(~p) HTTP/1.0\r\n\r\n",[30000])),
- case httpd_test_lib:verify_request(Type, Host, Port, Node, Req,
- [{statuscode, StatusCode},
- {version, "HTTP/1.0"}], Timeout) of
- ok ->
- exit(normal);
- 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_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index 1cecd2642c..b6525037b2 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -23,7 +23,8 @@
-include("inets_test_lib.hrl").
%% Poll functions
--export([verify_request/6, verify_request/7, verify_request/8, is_expect/1]).
+-export([verify_request/6, verify_request/7, verify_request/8, is_expect/1,
+ verify_request_N/9]).
-record(state, {request, % string()
socket, % socket()
@@ -109,9 +110,9 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
{error, Reason};
NewState ->
ValidateResult =
- validate(RequestStr, NewState, Options, Node, Port),
+ validate(RequestStr, NewState, Options, Node, Port),
inets_test_lib:close(SocketType, Socket),
- ValidateResult
+ ValidateResult
end;
ConnectError ->
@@ -126,6 +127,46 @@ verify_request(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, Ti
{args, [SocketType, Host, Port, TranspOpts]}]})
end.
+verify_request_N(SocketType, Host, Port, TranspOpts, Node, RequestStr, Options, TimeOut, N) ->
+ State = #state{},
+ try inets_test_lib:connect_bin(SocketType, Host, Port, TranspOpts) of
+ {ok, Socket} ->
+ request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port, State, N);
+ ConnectError ->
+ ct:fail({connect_error, ConnectError,
+ [SocketType, Host, Port, TranspOpts]})
+ catch
+ T:E ->
+ ct:fail({connect_failure,
+ [{type, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()},
+ {args, [SocketType, Host, Port, TranspOpts]}]})
+ end.
+
+request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port, State, 0) ->
+ ok = inets_test_lib:send(SocketType, Socket, RequestStr),
+ case request(State#state{request = RequestStr,
+ socket = Socket}, TimeOut) of
+ {error, Reason} ->
+ {error, Reason};
+ NewState ->
+ ValidateResult =
+ validate(RequestStr, NewState, Options, Node, Port),
+ inets_test_lib:close(SocketType, Socket),
+ ValidateResult
+ end;
+request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port, State, N) ->
+ ok = inets_test_lib:send(SocketType, Socket, RequestStr),
+ case request(State#state{request = RequestStr,
+ socket = Socket}, TimeOut) of
+ {error, Reason} ->
+ {error, Reason};
+ _NewState ->
+ request_N(SocketType, Socket, RequestStr, Options, TimeOut, Node, Port,
+ #state{}, N-1)
+ end.
+
request(#state{mfa = {Module, Function, Args},
request = RequestStr, socket = Socket} = State, TimeOut) ->
@@ -160,13 +201,35 @@ request(#state{mfa = {Module, Function, Args},
{ssl_closed, Socket} ->
exit({test_failed, connection_closed});
{ssl_error, Socket, Reason} ->
- ct:fail({ssl_error, Reason})
+ ct:fail({ssl_error, Reason});
+ {Socket, {data, Data}} when is_port(Socket) ->
+ case Module:Function([list_to_binary(Data) | Args]) of
+ {ok, Parsed} ->
+ port_handle_http_msg(Parsed, State);
+ {_, whole_body, _} when HeadRequest =:= "HEAD" ->
+ State#state{body = <<>>};
+ NewMFA ->
+ request(State#state{mfa = NewMFA}, TimeOut)
+ end;
+ {Socket, closed} when Function =:= whole_body ->
+ State#state{body = hd(Args)};
+ {Socket, closed} ->
+ exit({test_failed, connection_closed})
after TimeOut ->
ct:pal("~p ~w[~w]request -> timeout"
- "~n", [self(), ?MODULE, ?LINE]),
+ "~p~n", [self(), ?MODULE, ?LINE, Args]),
ct:fail(connection_timed_out)
end.
+
+port_handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body}, State) ->
+ State#state{status_line = {Version,
+ StatusCode,
+ ReasonPharse},
+ headers = Headers,
+ body = Body}.
+
+
handle_http_msg({Version, StatusCode, ReasonPharse, Headers, Body},
State = #state{request = RequestStr}) ->
case is_expect(RequestStr) of
diff --git a/lib/inets/test/inets.spec b/lib/inets/test/inets.spec
index ed102f8219..6cb3d6526c 100644
--- a/lib/inets/test/inets.spec
+++ b/lib/inets/test/inets.spec
@@ -1 +1,3 @@
-{suites,"../inets_test",all}.
+{suites,"../inets_test", all}.
+{skip_suites, "../inets_test", [httpd_bench_SUITE],
+ "Benchmarks run separately"}.
diff --git a/lib/inets/test/inets_bench.spec b/lib/inets/test/inets_bench.spec
new file mode 100644
index 0000000000..19136e691b
--- /dev/null
+++ b/lib/inets/test/inets_bench.spec
@@ -0,0 +1 @@
+{suites,"../inets_test",[httpd_bench_SUITE]}.
diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl
index f1185f7574..2529cc5f9b 100644
--- a/lib/inets/test/inets_test_lib.erl
+++ b/lib/inets/test/inets_test_lib.erl
@@ -463,8 +463,9 @@ connect_bin(essl, Host, Port, Opts0) ->
connect(ssl, Host, Port, Opts);
connect_bin(ip_comm, Host, Port, Opts0) ->
Opts = [binary, {packet, 0} | Opts0],
- connect(ip_comm, Host, Port, Opts).
-
+ connect(ip_comm, Host, Port, Opts);
+connect_bin(Type, Host, Port, Opts) ->
+ connect(Type, Host, Port, Opts).
connect_byte(SockType, Host, Port) ->
connect_byte(SockType, Host, Port, []).
@@ -477,27 +478,40 @@ connect_byte(essl, Host, Port, Opts0) ->
connect(ssl, Host, Port, Opts);
connect_byte(ip_comm, Host, Port, Opts0) ->
Opts = [{packet,0} | Opts0],
- connect(ip_comm, Host, Port, Opts).
+ connect(ip_comm, Host, Port, Opts);
+connect_byte(Type, Host, Port, Opts) ->
+ connect(Type, Host, Port, Opts).
connect(ip_comm, Host, Port, Opts) ->
gen_tcp:connect(Host, Port, Opts);
connect(ssl, Host, Port, Opts) ->
- ssl:connect(Host, Port, Opts).
+ ssl:connect(Host, Port, Opts);
+connect(openssl_port, Host, Port, Opts) ->
+ CaCertFile = proplists:get_value(cacertfile, Opts),
+ Cmd = "openssl s_client -quiet -port " ++ integer_to_list(Port) ++ " -host " ++ Host
+ ++ " -CAfile " ++ CaCertFile,
+ ct:log("openssl cmd: ~p~n", [Cmd]),
+ OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]),
+ read_junk(OpensslPort),
+ {ok, OpensslPort}.
send(ssl, Socket, Data) ->
ssl:send(Socket, Data);
send(essl, Socket, Data) ->
ssl:send(Socket, Data);
send(ip_comm,Socket,Data) ->
- gen_tcp:send(Socket,Data).
-
-
+ gen_tcp:send(Socket,Data);
+send(openssl_port, Port, Data) ->
+ true = port_command(Port, Data),
+ ok.
close(ssl,Socket) ->
catch ssl:close(Socket);
close(essl,Socket) ->
catch ssl:close(Socket);
close(ip_comm,Socket) ->
- catch gen_tcp:close(Socket).
+ catch gen_tcp:close(Socket);
+close(openssl_port, Port) ->
+ exit(Port, normal).
hours(N) -> trunc(N * 1000 * 60 * 60).
@@ -572,3 +586,11 @@ do_inet_port(Node) ->
{ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
{ok, Port} = rpc:call(Node, inet, port, [Socket]),
{Port, Socket}.
+
+read_junk(OpensslPort) ->
+ receive
+ {OpensslPort, _} ->
+ read_junk(OpensslPort)
+ after 500 ->
+ ok
+ end.
diff --git a/lib/inets/test/make_certs.erl b/lib/inets/test/make_certs.erl
new file mode 100644
index 0000000000..7215a59823
--- /dev/null
+++ b/lib/inets/test/make_certs.erl
@@ -0,0 +1,530 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(make_certs).
+-compile([export_all]).
+
+%-export([all/1, all/2, rootCA/2, intermediateCA/3, endusers/3, enduser/3, revoke/3, gencrl/2, verify/3]).
+
+-record(config, {commonName,
+ organizationalUnitName = "Erlang OTP",
+ organizationName = "Ericsson AB",
+ localityName = "Stockholm",
+ countryName = "SE",
+ emailAddress = "[email protected]",
+ default_bits = 2048,
+ v2_crls = true,
+ ecc_certs = false,
+ issuing_distribution_point = false,
+ crl_port = 8000,
+ openssl_cmd = "openssl"}).
+
+
+default_config() ->
+ #config{}.
+
+make_config(Args) ->
+ make_config(Args, #config{}).
+
+make_config([], C) ->
+ C;
+make_config([{organizationalUnitName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{organizationalUnitName = Name});
+make_config([{organizationName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{organizationName = Name});
+make_config([{localityName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{localityName = Name});
+make_config([{countryName, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{countryName = Name});
+make_config([{emailAddress, Name}|T], C) when is_list(Name) ->
+ make_config(T, C#config{emailAddress = Name});
+make_config([{default_bits, Bits}|T], C) when is_integer(Bits) ->
+ make_config(T, C#config{default_bits = Bits});
+make_config([{v2_crls, Bool}|T], C) when is_boolean(Bool) ->
+ make_config(T, C#config{v2_crls = Bool});
+make_config([{crl_port, Port}|T], C) when is_integer(Port) ->
+ make_config(T, C#config{crl_port = Port});
+make_config([{ecc_certs, Bool}|T], C) when is_boolean(Bool) ->
+ make_config(T, C#config{ecc_certs = Bool});
+make_config([{issuing_distribution_point, Bool}|T], C) when is_boolean(Bool) ->
+ make_config(T, C#config{issuing_distribution_point = Bool});
+make_config([{openssl_cmd, Cmd}|T], C) when is_list(Cmd) ->
+ make_config(T, C#config{openssl_cmd = Cmd}).
+
+
+all([DataDir, PrivDir]) ->
+ all(DataDir, PrivDir).
+
+all(DataDir, PrivDir) ->
+ all(DataDir, PrivDir, #config{}).
+
+all(DataDir, PrivDir, C) when is_list(C) ->
+ all(DataDir, PrivDir, make_config(C));
+all(DataDir, PrivDir, C = #config{}) ->
+ ok = filelib:ensure_dir(filename:join(PrivDir, "erlangCA")),
+ create_rnd(DataDir, PrivDir), % For all requests
+ rootCA(PrivDir, "erlangCA", C),
+ intermediateCA(PrivDir, "otpCA", "erlangCA", C),
+ endusers(PrivDir, "otpCA", ["client", "server", "revoked", "a.server", "b.server"], C),
+ endusers(PrivDir, "erlangCA", ["localhost"], C),
+ %% Create keycert files
+ SDir = filename:join([PrivDir, "server"]),
+ SC = filename:join([SDir, "cert.pem"]),
+ SK = filename:join([SDir, "key.pem"]),
+ SKC = filename:join([SDir, "keycert.pem"]),
+ append_files([SK, SC], SKC),
+ CDir = filename:join([PrivDir, "client"]),
+ CC = filename:join([CDir, "cert.pem"]),
+ CK = filename:join([CDir, "key.pem"]),
+ CKC = filename:join([CDir, "keycert.pem"]),
+ append_files([CK, CC], CKC),
+ RDir = filename:join([PrivDir, "revoked"]),
+ RC = filename:join([RDir, "cert.pem"]),
+ RK = filename:join([RDir, "key.pem"]),
+ RKC = filename:join([RDir, "keycert.pem"]),
+ revoke(PrivDir, "otpCA", "revoked", C),
+ append_files([RK, RC], RKC),
+ remove_rnd(PrivDir),
+ {ok, C}.
+
+append_files(FileNames, ResultFileName) ->
+ {ok, ResultFile} = file:open(ResultFileName, [write]),
+ do_append_files(FileNames, ResultFile).
+
+do_append_files([], RF) ->
+ ok = file:close(RF);
+do_append_files([F|Fs], RF) ->
+ {ok, Data} = file:read_file(F),
+ ok = file:write(RF, Data),
+ do_append_files(Fs, RF).
+
+rootCA(Root, Name, C) ->
+ create_ca_dir(Root, Name, ca_cnf(C#config{commonName = Name})),
+ create_self_signed_cert(Root, Name, req_cnf(C#config{commonName = Name}), C),
+ file:copy(filename:join([Root, Name, "cert.pem"]), filename:join([Root, Name, "cacerts.pem"])),
+ gencrl(Root, Name, C).
+
+intermediateCA(Root, CA, ParentCA, C) ->
+ create_ca_dir(Root, CA, ca_cnf(C#config{commonName = CA})),
+ CARoot = filename:join([Root, CA]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, req_cnf(C#config{commonName = CA})),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ ReqFile = filename:join([CARoot, "req.pem"]),
+ create_req(Root, CnfFile, KeyFile, ReqFile, C),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ sign_req(Root, ParentCA, "ca_cert", ReqFile, CertFile, C),
+ CACertsFile = filename:join(CARoot, "cacerts.pem"),
+ file:copy(filename:join([Root, ParentCA, "cacerts.pem"]), CACertsFile),
+ %% append this CA's cert to the cacerts file
+ {ok, Bin} = file:read_file(CertFile),
+ {ok, FD} = file:open(CACertsFile, [append]),
+ file:write(FD, ["\n", Bin]),
+ file:close(FD),
+ gencrl(Root, CA, C).
+
+endusers(Root, CA, Users, C) ->
+ [enduser(Root, CA, User, C) || User <- Users].
+
+enduser(Root, CA, User, C) ->
+ UsrRoot = filename:join([Root, User]),
+ file:make_dir(UsrRoot),
+ CnfFile = filename:join([UsrRoot, "req.cnf"]),
+ file:write_file(CnfFile, req_cnf(C#config{commonName = User})),
+ KeyFile = filename:join([UsrRoot, "key.pem"]),
+ ReqFile = filename:join([UsrRoot, "req.pem"]),
+ create_req(Root, CnfFile, KeyFile, ReqFile, C),
+ %create_req(Root, CnfFile, KeyFile, ReqFile),
+ CertFileAllUsage = filename:join([UsrRoot, "cert.pem"]),
+ sign_req(Root, CA, "user_cert", ReqFile, CertFileAllUsage, C),
+ CertFileDigitalSigOnly = filename:join([UsrRoot, "digital_signature_only_cert.pem"]),
+ sign_req(Root, CA, "user_cert_digital_signature_only", ReqFile, CertFileDigitalSigOnly, C),
+ CACertsFile = filename:join(UsrRoot, "cacerts.pem"),
+ file:copy(filename:join([Root, CA, "cacerts.pem"]), CACertsFile),
+ ok.
+
+revoke(Root, CA, User, C) ->
+ UsrCert = filename:join([Root, User, "cert.pem"]),
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -revoke ", UsrCert,
+ [" -crl_reason keyCompromise" || C#config.v2_crls ],
+ " -config ", CACnfFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env),
+ gencrl(Root, CA, C).
+
+gencrl(Root, CA, C) ->
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ CACRLFile = filename:join([Root, CA, "crl.pem"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -gencrl ",
+ " -crlhours 24",
+ " -out ", CACRLFile,
+ " -config ", CACnfFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
+verify(Root, CA, User, C) ->
+ CAFile = filename:join([Root, User, "cacerts.pem"]),
+ CACRLFile = filename:join([Root, CA, "crl.pem"]),
+ CertFile = filename:join([Root, User, "cert.pem"]),
+ Cmd = [C#config.openssl_cmd, " verify"
+ " -CAfile ", CAFile,
+ " -CRLfile ", CACRLFile, %% this is undocumented, but seems to work
+ " -crl_check ",
+ CertFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ try cmd(Cmd, Env) catch
+ exit:{eval_cmd, _, _} ->
+ invalid
+ end.
+
+create_self_signed_cert(Root, CAName, Cnf, C = #config{ecc_certs = true}) ->
+ CARoot = filename:join([Root, CAName]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, Cnf),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ Cmd = [C#config.openssl_cmd, " ecparam"
+ " -out ", KeyFile,
+ " -name secp521r1 ",
+ %" -name sect283k1 ",
+ " -genkey "],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env),
+
+ Cmd2 = [C#config.openssl_cmd, " req"
+ " -new"
+ " -x509"
+ " -config ", CnfFile,
+ " -key ", KeyFile,
+ " -outform PEM ",
+ " -out ", CertFile],
+ cmd(Cmd2, Env);
+create_self_signed_cert(Root, CAName, Cnf, C) ->
+ CARoot = filename:join([Root, CAName]),
+ CnfFile = filename:join([CARoot, "req.cnf"]),
+ file:write_file(CnfFile, Cnf),
+ KeyFile = filename:join([CARoot, "private", "key.pem"]),
+ CertFile = filename:join([CARoot, "cert.pem"]),
+ Cmd = [C#config.openssl_cmd, " req"
+ " -new"
+ " -x509"
+ " -config ", CnfFile,
+ " -keyout ", KeyFile,
+ " -outform PEM",
+ " -out ", CertFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
+
+create_ca_dir(Root, CAName, Cnf) ->
+ CARoot = filename:join([Root, CAName]),
+ ok = filelib:ensure_dir(CARoot),
+ file:make_dir(CARoot),
+ create_dirs(CARoot, ["certs", "crl", "newcerts", "private"]),
+ create_rnd(Root, filename:join([CAName, "private"])),
+ create_files(CARoot, [{"serial", "01\n"},
+ {"crlnumber", "01"},
+ {"index.txt", ""},
+ {"ca.cnf", Cnf}]).
+
+create_req(Root, CnfFile, KeyFile, ReqFile, C = #config{ecc_certs = true}) ->
+ Cmd = [C#config.openssl_cmd, " ecparam"
+ " -out ", KeyFile,
+ " -name secp521r1 ",
+ %" -name sect283k1 ",
+ " -genkey "],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env),
+ Cmd2 = [C#config.openssl_cmd, " req"
+ " -new ",
+ " -key ", KeyFile,
+ " -outform PEM ",
+ " -out ", ReqFile,
+ " -config ", CnfFile],
+ cmd(Cmd2, Env);
+ %fix_key_file(KeyFile).
+create_req(Root, CnfFile, KeyFile, ReqFile, C) ->
+ Cmd = [C#config.openssl_cmd, " req"
+ " -new"
+ " -config ", CnfFile,
+ " -outform PEM ",
+ " -keyout ", KeyFile,
+ " -out ", ReqFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+ %fix_key_file(KeyFile).
+
+
+sign_req(Root, CA, CertType, ReqFile, CertFile, C) ->
+ CACnfFile = filename:join([Root, CA, "ca.cnf"]),
+ Cmd = [C#config.openssl_cmd, " ca"
+ " -batch"
+ " -notext"
+ " -config ", CACnfFile,
+ " -extensions ", CertType,
+ " -in ", ReqFile,
+ " -out ", CertFile],
+ Env = [{"ROOTDIR", filename:absname(Root)}],
+ cmd(Cmd, Env).
+
+%%
+%% Misc
+%%
+
+create_dirs(Root, Dirs) ->
+ lists:foreach(fun(Dir) ->
+ file:make_dir(filename:join([Root, Dir])) end,
+ Dirs).
+
+create_files(Root, NameContents) ->
+ lists:foreach(
+ fun({Name, Contents}) ->
+ file:write_file(filename:join([Root, Name]), Contents) end,
+ NameContents).
+
+create_rnd(FromDir, ToDir) ->
+ From = filename:join([FromDir, "RAND"]),
+ To = filename:join([ToDir, "RAND"]),
+ file:copy(From, To).
+
+remove_rnd(Dir) ->
+ File = filename:join([Dir, "RAND"]),
+ file:delete(File).
+
+cmd(Cmd, Env) ->
+ FCmd = lists:flatten(Cmd),
+ Port = open_port({spawn, FCmd}, [stream, eof, exit_status, stderr_to_stdout,
+ {env, Env}]),
+ eval_cmd(Port, FCmd).
+
+eval_cmd(Port, Cmd) ->
+ receive
+ {Port, {data, _}} ->
+ eval_cmd(Port, Cmd);
+ {Port, eof} ->
+ ok
+ end,
+ receive
+ {Port, {exit_status, 0}} ->
+ ok;
+ {Port, {exit_status, Status}} ->
+ exit({eval_cmd, Cmd, Status})
+ after 0 ->
+ ok
+ end.
+
+%%
+%% Contents of configuration files
+%%
+
+req_cnf(C) ->
+ ["# Purpose: Configuration for requests (end users and CAs)."
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "\n"
+
+ "[req]\n"
+ "input_password = secret\n"
+ "output_password = secret\n"
+ "default_bits = ", integer_to_list(C#config.default_bits), "\n"
+ "RANDFILE = $ROOTDIR/RAND\n"
+ "encrypt_key = no\n"
+ "default_md = md5\n"
+ "#string_mask = pkix\n"
+ "x509_extensions = ca_ext\n"
+ "prompt = no\n"
+ "distinguished_name= name\n"
+ "\n"
+
+ "[name]\n"
+ "commonName = ", C#config.commonName, "\n"
+ "organizationalUnitName = ", C#config.organizationalUnitName, "\n"
+ "organizationName = ", C#config.organizationName, "\n"
+ "localityName = ", C#config.localityName, "\n"
+ "countryName = ", C#config.countryName, "\n"
+ "emailAddress = ", C#config.emailAddress, "\n"
+ "\n"
+
+ "[ca_ext]\n"
+ "basicConstraints = critical, CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "subjectAltName = email:copy\n"].
+
+ca_cnf(C = #config{issuing_distribution_point = true}) ->
+ ["# Purpose: Configuration for CAs.\n"
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "default_ca = ca\n"
+ "\n"
+
+ "[ca]\n"
+ "dir = $ROOTDIR/", C#config.commonName, "\n"
+ "certs = $dir/certs\n"
+ "crl_dir = $dir/crl\n"
+ "database = $dir/index.txt\n"
+ "new_certs_dir = $dir/newcerts\n"
+ "certificate = $dir/cert.pem\n"
+ "serial = $dir/serial\n"
+ "crl = $dir/crl.pem\n",
+ ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls],
+ "private_key = $dir/private/key.pem\n"
+ "RANDFILE = $dir/private/RAND\n"
+ "\n"
+ "x509_extensions = user_cert\n",
+ ["crl_extensions = crl_ext\n" || C#config.v2_crls],
+ "unique_subject = no\n"
+ "default_days = 3600\n"
+ "default_md = md5\n"
+ "preserve = no\n"
+ "policy = policy_match\n"
+ "\n"
+
+ "[policy_match]\n"
+ "commonName = supplied\n"
+ "organizationalUnitName = optional\n"
+ "organizationName = match\n"
+ "countryName = match\n"
+ "localityName = match\n"
+ "emailAddress = supplied\n"
+ "\n"
+
+ "[crl_ext]\n"
+ "authorityKeyIdentifier=keyid:always,issuer:always\n",
+ ["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point],
+
+ "[idpsec]\n"
+ "fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n"
+
+ "[user_cert]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "crlDistributionPoints=@crl_section\n"
+
+ "[crl_section]\n"
+ %% intentionally invalid
+ "URI.1=http://localhost/",C#config.commonName,"/crl.pem\n"
+ "URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n"
+ "\n"
+
+ "[user_cert_digital_signature_only]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = digitalSignature\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "\n"
+
+ "[ca_cert]\n"
+ "basicConstraints = critical,CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid:always,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "crlDistributionPoints=@crl_section\n"
+ ];
+
+ca_cnf(C = #config{issuing_distribution_point = false}) ->
+ ["# Purpose: Configuration for CAs.\n"
+ "\n"
+ "ROOTDIR = $ENV::ROOTDIR\n"
+ "default_ca = ca\n"
+ "\n"
+
+ "[ca]\n"
+ "dir = $ROOTDIR/", C#config.commonName, "\n"
+ "certs = $dir/certs\n"
+ "crl_dir = $dir/crl\n"
+ "database = $dir/index.txt\n"
+ "new_certs_dir = $dir/newcerts\n"
+ "certificate = $dir/cert.pem\n"
+ "serial = $dir/serial\n"
+ "crl = $dir/crl.pem\n",
+ ["crlnumber = $dir/crlnumber\n" || C#config.v2_crls],
+ "private_key = $dir/private/key.pem\n"
+ "RANDFILE = $dir/private/RAND\n"
+ "\n"
+ "x509_extensions = user_cert\n",
+ ["crl_extensions = crl_ext\n" || C#config.v2_crls],
+ "unique_subject = no\n"
+ "default_days = 3600\n"
+ "default_md = md5\n"
+ "preserve = no\n"
+ "policy = policy_match\n"
+ "\n"
+
+ "[policy_match]\n"
+ "commonName = supplied\n"
+ "organizationalUnitName = optional\n"
+ "organizationName = match\n"
+ "countryName = match\n"
+ "localityName = match\n"
+ "emailAddress = supplied\n"
+ "\n"
+
+ "[crl_ext]\n"
+ "authorityKeyIdentifier=keyid:always,issuer:always\n",
+ %["issuingDistributionPoint=critical, @idpsec\n" || C#config.issuing_distribution_point],
+
+ %"[idpsec]\n"
+ %"fullname=URI:http://localhost:8000/",C#config.commonName,"/crl.pem\n"
+
+ "[user_cert]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ %"crlDistributionPoints=@crl_section\n"
+
+ %%"[crl_section]\n"
+ %% intentionally invalid
+ %%"URI.1=http://localhost/",C#config.commonName,"/crl.pem\n"
+ %%"URI.2=http://localhost:",integer_to_list(C#config.crl_port),"/",C#config.commonName,"/crl.pem\n"
+ %%"\n"
+
+ "[user_cert_digital_signature_only]\n"
+ "basicConstraints = CA:false\n"
+ "keyUsage = digitalSignature\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ "\n"
+
+ "[ca_cert]\n"
+ "basicConstraints = critical,CA:true\n"
+ "keyUsage = cRLSign, keyCertSign\n"
+ "subjectKeyIdentifier = hash\n"
+ "authorityKeyIdentifier = keyid:always,issuer:always\n"
+ "subjectAltName = email:copy\n"
+ "issuerAltName = issuer:copy\n"
+ %"crlDistributionPoints=@crl_section\n"
+ ].
diff --git a/lib/inets/test/old_httpd_SUITE.erl b/lib/inets/test/old_httpd_SUITE.erl
deleted file mode 100644
index 172db53844..0000000000
--- a/lib/inets/test/old_httpd_SUITE.erl
+++ /dev/null
@@ -1,2347 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
--module(old_httpd_SUITE).
-
--include_lib("common_test/include/ct.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,
- %% Only used through load_config
- %% but we still need these tests
- %% should be cleaned up and moved to new test suite
- %%ip_restart_no_block,
- %%ip_restart_disturbing_block,
- %%ip_restart_non_disturbing_block,
- %% Tested in inets_SUITE
- %%ip_block_disturbing_idle,
- %%ip_block_non_disturbing_idle,
- ip_block_503
- %% Tested in new httpd_SUITE
- %%ip_block_disturbing_active,
- %%ip_block_non_disturbing_active,
- %%ip_block_disturbing_blocker_dies,
- %%ip_block_non_disturbing_blocker_dies
- %% No longer relevant
- %%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,
- ]},
- {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
- %% Replaced by load_config
- %% 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]),
-
- PrivDir = proplists:get_value(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 = proplists:get_value(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 = proplists:get_value(data_dir, Config),
- SuiteTopDir = proplists:get_value(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 = proplists:get_value(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(proplists:get_value(node, Config)),
- [{watchdog, Dog} | NewConfig];
- "mod_htaccess" ->
- ServerRoot = proplists:get_value(server_root, Config),
- Path = filename:join([ServerRoot, "htdocs"]),
- catch remove_htaccess(Path),
- create_htaccess_data(Path, proplists:get_value(address, Config)),
- [{watchdog, Dog} | NewConfig];
- "range" ->
- ServerRoot = proplists:get_value(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 = proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(node, Config)),
- ok.
-
-%%-------------------------------------------------------------------------
-ip_mod_security(doc) ->
- ["Module test: mod_security"];
-ip_mod_security(suite) ->
- [];
-ip_mod_security(Config) when is_list(Config) ->
- ServerRoot = proplists:get_value(server_root, Config),
- httpd_mod:security(ServerRoot, ip_comm, ?IP_PORT,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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 = proplists:get_value(server_root, Config),
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(node, Config), ?MAX_HEADER_SIZE),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ip_time_test(doc) ->
- [""];
-ip_time_test(suite) ->
- [];
-ip_time_test(Config) when is_list(Config) ->
- httpd_time_test:t(ip_comm, proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host,
- Config),
- proplists:get_value(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,
- proplists:get_value(host,
- Config),
- proplists:get_value(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,
- proplists:get_value(host,
- Config),
- proplists:get_value(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,
- proplists:get_value(host,
- Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(node, Config)),
- ok.
-%%-------------------------------------------------------------------------
-ip_restart_disturbing_block(doc) ->
- [""];
-ip_restart_disturbing_block(suite) ->
- [];
-ip_restart_disturbing_block(Config) when is_list(Config) ->
- httpd_block:restart_disturbing_block(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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) ->
- httpd_block:restart_non_disturbing_block(ip_comm, ?IP_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config), proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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 = proplists:get_value(server_root, Config),
- httpd_mod:security(ServerRoot,
- Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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 = proplists:get_value(server_root, Config),
- Host = proplists:get_value(host, Config),
- Node = proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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) ->
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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) ->
- httpd_load:load_test(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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) ->
- httpd_time_test:t(Tag,
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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,
- proplists:get_value(host, Config),
- proplists:get_value(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) ->
- httpd_block:restart_disturbing_block(Tag, ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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) ->
- httpd_block:restart_non_disturbing_block(Tag,
- ?SSL_PORT,
- proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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 = proplists:get_value(server_root, Config),
- DocRoot = filename:join([ServerRoot, "htdocs"]),
- httpd_1_1:if_test(ip_comm, ?IP_PORT, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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, proplists:get_value(host, Config),
- proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(host, Config),
- Node = proplists:get_value(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 = proplists:get_value(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,
- proplists:get_value(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 = proplists:get_value(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 = proplists:get_value(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, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(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) ->
- ct:skip(as_of_r15_behaviour_of_calendar_has_changed),
- Host = proplists:get_value(host,Config),
- ServerRoot = proplists:get_value(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, proplists:get_value(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, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(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, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(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, proplists:get_value(host, Config),
- ?IP_PORT, proplists:get_value(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 = proplists:get_value(server_root, Config),
- TcTopDir = proplists:get_value(tc_top_dir, Config),
- Port = proplists:get_value(port, Config),
- Type = proplists:get_value(sock_type, Config),
- Host = proplists:get_value(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_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_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 = proplists:get_value(server_root, Config),
- TcTopDir = proplists:get_value(tc_top_dir, Config),
- Port = proplists:get_value(port, Config),
- SockType = proplists:get_value(sock_type, Config),
- Mods = io_lib:format("~p", [httpd_mod]),
- Funcs = io_lib:format("~p", [ssl_password_cb]),
- Host = proplists:get_value(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_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
deleted file mode 100644
index b0fdb43d8d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/Makefile.src
+++ /dev/null
@@ -1,14 +0,0 @@
-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
deleted file mode 100644
index 580f860e96..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/cgi_echo.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#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/old_httpd_SUITE_data/server_root/Makefile b/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
deleted file mode 100644
index ed4d63a3bb..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/Makefile
+++ /dev/null
@@ -1,210 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-include $(ERL_TOP)/make/target.mk
-include $(ERL_TOP)/make/$(TARGET)/otp.mk
-
-# ----------------------------------------------------
-# Application version
-# ----------------------------------------------------
-include ../../vsn.mk
-VSN=$(INETS_VSN)
-
-# ----------------------------------------------------
-# Release directory specification
-# ----------------------------------------------------
-RELSYSDIR = $(RELEASE_PATH)/lib/inets-$(VSN)
-
-# ----------------------------------------------------
-# Target Specs
-# ----------------------------------------------------
-MODULE=
-
-AUTH_FILES = auth/group \
- 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
-MISC_FILES = htdocs/misc/friedrich.html \
- htdocs/misc/oech.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 \
- htdocs/exec.shtml \
- htdocs/flastmod.shtml \
- htdocs/fsize.shtml \
- htdocs/include.shtml
-ICON_FILES = icons/README \
- icons/a.gif \
- icons/alert.black.gif \
- icons/alert.red.gif \
- icons/apache_pb.gif \
- icons/back.gif \
- icons/ball.gray.gif \
- icons/ball.red.gif \
- icons/binary.gif \
- icons/binhex.gif \
- icons/blank.gif \
- icons/bomb.gif \
- icons/box1.gif \
- icons/box2.gif \
- icons/broken.gif \
- icons/burst.gif \
- icons/button1.gif \
- icons/button10.gif \
- icons/button2.gif \
- icons/button3.gif \
- icons/button4.gif \
- icons/button5.gif \
- icons/button6.gif \
- icons/button7.gif \
- icons/button8.gif \
- icons/button9.gif \
- icons/buttonl.gif \
- icons/buttonr.gif \
- icons/c.gif \
- icons/comp.blue.gif \
- icons/comp.gray.gif \
- icons/compressed.gif \
- icons/continued.gif \
- icons/dir.gif \
- icons/down.gif \
- icons/dvi.gif \
- icons/f.gif \
- icons/folder.gif \
- icons/folder.open.gif \
- icons/folder.sec.gif \
- icons/forward.gif \
- icons/generic.gif \
- icons/generic.red.gif \
- icons/generic.sec.gif \
- icons/hand.right.gif \
- icons/hand.up.gif \
- icons/htdig.gif \
- icons/icon.sheet.gif \
- icons/image1.gif \
- icons/image2.gif \
- icons/image3.gif \
- icons/index.gif \
- icons/layout.gif \
- icons/left.gif \
- icons/link.gif \
- icons/movie.gif \
- icons/p.gif \
- icons/patch.gif \
- icons/pdf.gif \
- icons/pie0.gif \
- icons/pie1.gif \
- icons/pie2.gif \
- icons/pie3.gif \
- icons/pie4.gif \
- icons/pie5.gif \
- icons/pie6.gif \
- icons/pie7.gif \
- icons/pie8.gif \
- icons/portal.gif \
- icons/poweredby.gif \
- icons/ps.gif \
- icons/quill.gif \
- icons/right.gif \
- icons/screw1.gif \
- icons/screw2.gif \
- icons/script.gif \
- icons/sound1.gif \
- icons/sound2.gif \
- icons/sphere1.gif \
- icons/sphere2.gif \
- icons/star.gif \
- icons/star_blank.gif \
- icons/tar.gif \
- icons/tex.gif \
- icons/text.gif \
- icons/transfer.gif \
- icons/unknown.gif \
- icons/up.gif \
- icons/uu.gif \
- icons/uuencoded.gif \
- icons/world1.gif \
- icons/world2.gif
-
-SSL_FILES = ssl/ssl_client.pem \
- ssl/ssl_server.pem
-
-# ----------------------------------------------------
-# FLAGS
-# ----------------------------------------------------
-ERL_COMPILE_FLAGS +=
-
-# ----------------------------------------------------
-# Targets
-# ----------------------------------------------------
-
-debug opt:
-
-clean:
-
-docs:
-
-# ----------------------------------------------------
-# Release Target
-# ----------------------------------------------------
-include $(ERL_TOP)/make/otp_release_targets.mk
-
-release_spec: opt
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/auth
- $(INSTALL_DATA) $(AUTH_FILES) $(RELSYSDIR)/examples/server_root/auth
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/cgi-bin
- $(INSTALL_SCRIPT) $(CGI_FILES) $(RELSYSDIR)/examples/server_root/cgi-bin
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/conf
- $(INSTALL_DATA) $(CONF_FILES) $(RELSYSDIR)/examples/server_root/conf
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/open
- $(INSTALL_DATA) $(OPEN_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/open
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/mnesia_open
- $(INSTALL_DATA) $(MNESIA_OPEN_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_open
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs/misc
- $(INSTALL_DATA) $(MISC_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/misc
- $(INSTALL_DIR) \
- $(RELSYSDIR)/examples/server_root/htdocs/secret/top_secret
- $(INSTALL_DIR) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret/top_secret
- $(INSTALL_DATA) $(SECRET_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/secret
- $(INSTALL_DATA) $(MNESIA_SECRET_FILES) \
- $(RELSYSDIR)/examples/server_root/htdocs/mnesia_secret
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/htdocs
- $(INSTALL_DATA) $(HTDOCS_FILES) $(RELSYSDIR)/examples/server_root/htdocs
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/icons
- $(INSTALL_DATA) $(ICON_FILES) $(RELSYSDIR)/examples/server_root/icons
- $(INSTALL_DIR) $(RELSYSDIR)/examples/server_root/ssl
- $(INSTALL_DATA) $(SSL_FILES) $(RELSYSDIR)/examples/server_root/ssl
- $(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
deleted file mode 100644
index b3da0ccbd3..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/group
+++ /dev/null
@@ -1,3 +0,0 @@
-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
deleted file mode 100644
index 8c980ff547..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/auth/passwd
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644
index 25a49a1536..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@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
deleted file mode 100755
index de81de9bde..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/cgi-bin/printenv.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/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/old_httpd_SUITE_data/server_root/conf/8080.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
deleted file mode 100644
index 7b1b4a15b2..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf
+++ /dev/null
@@ -1,79 +0,0 @@
-Port 8080
-#ServerName your.server.net
-SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
-ServerAdmin [email protected]
-ServerRoot /var/tmp/server_root
-ErrorLog logs/error_log_8080
-TransferLog logs/access_log_8080
-SecurityLog logs/security_log_8080
-ErrorDiskLog logs/error_disk_log_8080
-ErrorDiskLogSize 200000 10
-TransferDiskLog logs/access_disk_log_8080
-TransferDiskLogSize 200000 10
-SecurityDiskLog logs/security_disk_log
-SecurityDiskLogSize 200000 10
-MaxClients 50
-#KeepAlive 5
-#KeepAliveTimeout 10
-DocumentRoot /var/tmp/server_root/htdocs
-DirectoryIndex index.html welcome.html
-DefaultType text/plain
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-ErlScriptAlias /cgi-bin/erl httpd_example io
-EvalScriptAlias /eval httpd_example io
-#Script HEAD /cgi-bin/printenv.sh
-#Action image/gif /cgi-bin/printenv.sh
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthDBType plain
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthDBType plain
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthDBType plain
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthDBType mnesia
-AuthName Open Area
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthDBType mnesia
-AuthName Secret Area
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthDBType mnesia
-AuthName Top Secret Area
-require group group3
-allow from 130.100.34 130.100.35
-deny from 100.234.22.12 194.100.34.1 130.100.34.25
-SecurityDataFile logs/security_data
-SecurityMaxRetries 3
-SecurityBlockTime 10
-SecurityFailExpireTime 1
-SecurityAuthTimeout 1
-SecurityCallbackModule security_callback
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
deleted file mode 100644
index 042779fcd0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf
+++ /dev/null
@@ -1,63 +0,0 @@
-Port 8888
-#ServerName your.server.net
-SocketType ip_comm
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
-ServerAdmin [email protected]
-ServerRoot /var/tmp/server_root
-ErrorLog logs/error_log_8888
-TransferLog logs/access_log_8888
-ErrorDiskLog logs/error_disk_log_8888
-ErrorDiskLogSize 200000 10
-TransferDiskLog logs/access_disk_log_8888
-TransferDiskLogSize 200000 10
-MaxClients 150
-DocumentRoot /var/tmp/server_root/htdocs
-DirectoryIndex index.html welcome.html
-DefaultType text/plain
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-ErlScriptAlias /cgi-bin/erl httpd_example io
-EvalScriptAlias /eval httpd_example io
-#Script HEAD /cgi-bin/printenv.sh
-#Action image/gif /cgi-bin/printenv.sh
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthName Open Area
-AuthMnesiaDB On
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthName Secret Area
-AuthMnesiaDB On
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthName Top Secret Area
-AuthMnesiaDB On
-require group group3
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
deleted file mode 100644
index 3add93cd73..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf
+++ /dev/null
@@ -1,269 +0,0 @@
-#
-# %CopyrightBegin%
-#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# %CopyrightEnd%
-#
-#
-
-# Port: The port the standalone listens to. For ports < 1023, you will
-# need httpd to be run as root initially.
-
-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.
-# Default value for ip-family is inet6fb4
-#
-# The syntax is: <address>[|<ip-family>]
-#
-#BindAddress *
-#BindAddress *|inet
-
-
-# ServerName allows you to set a host name which is sent back to clients for
-# 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
-# define here must be a valid DNS name for your host. If you don't understand
-# this, ask your network administrator.
-
-#ServerName your.server.net
-
-# SocketType is either ip_comm, sockets or ssl.
-
-SocketType ip_comm
-
-# Modules: Server run-time plug-in modules written using the Erlang
-# Web Server API (EWSAPI). The server API make it easy to add functionality
-# to the server. Read more about EWSAPI in the Reference Manual.
-# WARNING! Do not tamper with this directive unless you are familiar with
-# EWSAPI.
-
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log
-
-# ServerAdmin: Your address, where problems with the server should be
-# e-mailed.
-
-ServerAdmin [email protected]
-
-# ServerRoot: The directory the server's config, error, and log files
-# are kept in
-
-ServerRoot /var/tmp/server_root
-
-# ErrorLog: The location of the error log file. If this does not start
-# with /, ServerRoot is prepended to it.
-
-ErrorLog logs/error_log
-
-# TransferLog: The location of the transfer log file. If this does not
-# start with /, ServerRoot is prepended to it.
-
-TransferLog logs/access_log
-
-# SecurityLog: The location of the security log file (mod_security required)
-#
-SecurityLog logs/security_log
-
-# ErrorDiskLog: The location of the error log file. If this does not
-# start with /, ServerRoot is prepended to it. This log file is managed
-# with the disk_log module [See disk_log(3)]. The ErrorDiskLogSize directive
-# takes two argument, i.e. MaxBytes and MaxFiles. The wrap log writes at most
-# MaxBytes bytes on each file, and it uses MaxFiles files before it wraps, and
-# truncates the first file.
-
-ErrorDiskLog logs/error_disk_log
-ErrorDiskLogSize 200000 10
-
-# TransferDiskLog: The location of the transfer log file. If this does not
-# start with /, ServerRoot is prepended to it. This log file is managed
-# with the disk_log module [See disk_log(3)]. The TransferDiskLogSize directive
-# takes two argument, i.e. MaxBytes and MaxFiles. The wrap log writes at most
-# MaxBytes bytes on each file, and it uses MaxFiles files before it wraps, and
-# truncates the first file.
-
-TransferDiskLog logs/access_disk_log
-TransferDiskLogSize 200000 10
-
-# SecurityDiskLog: The location of the security log file. If this does not
-# start with /, ServerRoot is prepended to it. This log file is managed
-# with the disk_log module [See disk_log(3)]. The SecurityDiskLogSize directive
-# takes two argument, i.e. MaxBytes and MaxFiles. The wrap log writes at most
-# MaxBytes bytes on each file, and it uses MaxFiles files before it wraps, and
-# truncates the first file.
-
-SecurityDiskLog logs/security_disk_log
-SecurityDiskLogSize 200000 10
-
-# Limit on total number of servers running, i.e., limit on the number
-# of clients who can simultaneously connect --- if this limit is ever
-# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
-# It is intended mainly as a brake to keep a runaway server from taking
-# the server with it as it spirals down...
-
-MaxClients 50
-
-# KeepAlive set the flag for persistent connections. For persistent connections
-# set KeepAlive to on. To use One request per connection set the flag to off
-# Note: The value has changed since previous version of INETS.
-KeepAlive on
-
-# KeepAliveTimeout sets the number of seconds before a persistent connection
-# times out and closes.
-KeepAliveTimeout 10
-
-# MaxKeepAliveRequests sets the number of seconds before a persistent connection
-# times out and closes.
-MaxKeepAliveRequests 10
-
-
-
-# DocumentRoot: The directory out of which you will serve your
-# documents. By default, all requests are taken from this directory, but
-# symbolic links and aliases may be used to point to other locations.
-
-DocumentRoot /var/tmp/server_root/htdocs
-
-# DirectoryIndex: Name of the file or files to use as a pre-written HTML
-# directory index. Separate multiple entries with spaces.
-
-DirectoryIndex index.html welcome.html
-
-# DefaultType is the default MIME type for documents which the server
-# cannot find the type of from filename extensions.
-
-DefaultType text/plain
-
-# 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/
-Alias /pics/ /var/tmp/server_root/icons/
-
-# ScriptAlias: This controls which directories contain server scripts.
-# Format: ScriptAlias fakename realname
-
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-
-# This directive adds an action, which will activate cgi-script when a
-# file is requested using the method of method, which can be one of
-# GET, POST and HEAD. It sends the URL and file path of the requested
-# document using the standard CGI PATH_INFO and PATH_TRANSLATED
-# environment variables.
-
-#Script HEAD /cgi-bin/printenv.sh
-
-# This directive adds an action, which will activate cgi-script when a
-# file of content type mime-type is requested. It sends the URL and
-# file path of the requested document using the standard CGI PATH_INFO
-# and PATH_TRANSLATED environment variables.
-
-#Action image/gif /cgi-bin/printenv.sh
-
-# ErlScriptAlias: This specifies how "Erl" server scripts are called.
-# Format: ErlScriptAlias fakename realname allowed_modules
-
-ErlScriptAlias /down/erl httpd_example io
-
-# EvalScriptAlias: This specifies how "Eval" server scripts are called.
-# Format: EvalScriptAlias fakename realname allowed_modules
-
-EvalScriptAlias /eval httpd_example io
-
-# Point SSLCertificateFile at a PEM encoded certificate.
-
-SSLCertificateFile /var/tmp/server_root/ssl/ssl_server.pem
-
-# If the key is not combined with the certificate, use this directive to
-# point at the key file.
-
-SSLCertificateKeyFile /var/tmp/server_root/ssl/ssl_server.pem
-
-# Set SSLVerifyClient to:
-# 0 if no certicate is required
-# 1 if the client may present a valid certificate
-# 2 if the client must present a valid certificate
-# 3 if the client may present a valid certificate but it is not required to
-# have a valid CA
-
-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 /var/tmp/server_root/htdocs/open>
-AuthDBType plain
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthDBType plain
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthDBType plain
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthDBType mnesia
-AuthName Open Area
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthDBType mnesia
-AuthName Secret Area
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthDBType mnesia
-AuthName Top Secret Area
-require group group3
-allow from 130.100.34 130.100.35
-deny from 100.234.22.12 194.100.34.1 130.100.34.25
-SecurityDataFile logs/security_data
-SecurityMaxRetries 3
-SecurityBlockTime 10
-SecurityFailExpireTime 1
-SecurityAuthTimeout 1
-SecurityCallbackModule security_callback
-</Directory>
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types
deleted file mode 100644
index d2f81e4e5e..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/mime.types
+++ /dev/null
@@ -1,465 +0,0 @@
-# This is a comment. I love comments.
-
-# MIME type Extension
-application/EDI-Consent
-application/EDI-X12
-application/EDIFACT
-application/activemessage
-application/andrew-inset ez
-application/applefile
-application/atomicmail
-application/batch-SMTP
-application/beep+xml
-application/cals-1840
-application/commonground
-application/cybercash
-application/dca-rft
-application/dec-dx
-application/dvcs
-application/eshop
-application/http
-application/hyperstudio
-application/iges
-application/index
-application/index.cmd
-application/index.obj
-application/index.response
-application/index.vnd
-application/iotp
-application/ipp
-application/isup
-application/font-tdpfr
-application/mac-binhex40 hqx
-application/mac-compactpro cpt
-application/macwriteii
-application/marc
-application/mathematica
-application/mathematica-old
-application/msword doc
-application/news-message-id
-application/news-transmission
-application/ocsp-request
-application/ocsp-response
-application/octet-stream bin dms lha lzh exe class so dll
-application/oda oda
-application/parityfec
-application/pdf pdf
-application/pgp-encrypted
-application/pgp-keys
-application/pgp-signature
-application/pkcs10
-application/pkcs7-mime
-application/pkcs7-signature
-application/pkix-cert
-application/pkix-crl
-application/pkixcmp
-application/postscript ai eps ps
-application/prs.alvestrand.titrax-sheet
-application/prs.cww
-application/prs.nprend
-application/qsig
-application/remote-printing
-application/riscos
-application/rtf
-application/sdp
-application/set-payment
-application/set-payment-initiation
-application/set-registration
-application/set-registration-initiation
-application/sgml
-application/sgml-open-catalog
-application/sieve
-application/slate
-application/smil smi smil
-application/timestamp-query
-application/timestamp-reply
-application/vemmi
-application/vnd.3M.Post-it-Notes
-application/vnd.FloGraphIt
-application/vnd.accpac.simply.aso
-application/vnd.accpac.simply.imp
-application/vnd.acucobol
-application/vnd.aether.imp
-application/vnd.anser-web-certificate-issue-initiation
-application/vnd.anser-web-funds-transfer-initiation
-application/vnd.audiograph
-application/vnd.businessobjects
-application/vnd.bmi
-application/vnd.canon-cpdl
-application/vnd.canon-lips
-application/vnd.claymore
-application/vnd.commerce-battelle
-application/vnd.commonspace
-application/vnd.comsocaller
-application/vnd.contact.cmsg
-application/vnd.cosmocaller
-application/vnd.cups-postscript
-application/vnd.cups-raster
-application/vnd.cups-raw
-application/vnd.ctc-posml
-application/vnd.cybank
-application/vnd.dna
-application/vnd.dpgraph
-application/vnd.dxr
-application/vnd.ecdis-update
-application/vnd.ecowin.chart
-application/vnd.ecowin.filerequest
-application/vnd.ecowin.fileupdate
-application/vnd.ecowin.series
-application/vnd.ecowin.seriesrequest
-application/vnd.ecowin.seriesupdate
-application/vnd.enliven
-application/vnd.epson.esf
-application/vnd.epson.msf
-application/vnd.epson.quickanime
-application/vnd.epson.salt
-application/vnd.epson.ssf
-application/vnd.ericsson.quickcall
-application/vnd.eudora.data
-application/vnd.fdf
-application/vnd.ffsns
-application/vnd.framemaker
-application/vnd.fsc.weblaunch
-application/vnd.fujitsu.oasys
-application/vnd.fujitsu.oasys2
-application/vnd.fujitsu.oasys3
-application/vnd.fujitsu.oasysgp
-application/vnd.fujitsu.oasysprs
-application/vnd.fujixerox.ddd
-application/vnd.fujixerox.docuworks
-application/vnd.fujixerox.docuworks.binder
-application/vnd.fut-misnet
-application/vnd.grafeq
-application/vnd.groove-account
-application/vnd.groove-identity-message
-application/vnd.groove-injector
-application/vnd.groove-tool-message
-application/vnd.groove-tool-template
-application/vnd.groove-vcard
-application/vnd.hhe.lesson-player
-application/vnd.hp-HPGL
-application/vnd.hp-PCL
-application/vnd.hp-PCLXL
-application/vnd.hp-hpid
-application/vnd.hp-hps
-application/vnd.httphone
-application/vnd.hzn-3d-crossword
-application/vnd.ibm.afplinedata
-application/vnd.ibm.MiniPay
-application/vnd.ibm.modcap
-application/vnd.informix-visionary
-application/vnd.intercon.formnet
-application/vnd.intertrust.digibox
-application/vnd.intertrust.nncp
-application/vnd.intu.qbo
-application/vnd.intu.qfx
-application/vnd.irepository.package+xml
-application/vnd.is-xpr
-application/vnd.japannet-directory-service
-application/vnd.japannet-jpnstore-wakeup
-application/vnd.japannet-payment-wakeup
-application/vnd.japannet-registration
-application/vnd.japannet-registration-wakeup
-application/vnd.japannet-setstore-wakeup
-application/vnd.japannet-verification
-application/vnd.japannet-verification-wakeup
-application/vnd.koan
-application/vnd.lotus-1-2-3
-application/vnd.lotus-approach
-application/vnd.lotus-freelance
-application/vnd.lotus-notes
-application/vnd.lotus-organizer
-application/vnd.lotus-screencam
-application/vnd.lotus-wordpro
-application/vnd.mcd
-application/vnd.mediastation.cdkey
-application/vnd.meridian-slingshot
-application/vnd.mif mif
-application/vnd.minisoft-hp3000-save
-application/vnd.mitsubishi.misty-guard.trustweb
-application/vnd.mobius.daf
-application/vnd.mobius.dis
-application/vnd.mobius.msl
-application/vnd.mobius.plc
-application/vnd.mobius.txf
-application/vnd.motorola.flexsuite
-application/vnd.motorola.flexsuite.adsi
-application/vnd.motorola.flexsuite.fis
-application/vnd.motorola.flexsuite.gotap
-application/vnd.motorola.flexsuite.kmr
-application/vnd.motorola.flexsuite.ttc
-application/vnd.motorola.flexsuite.wem
-application/vnd.mozilla.xul+xml
-application/vnd.ms-artgalry
-application/vnd.ms-asf
-application/vnd.ms-excel xls
-application/vnd.ms-lrm
-application/vnd.ms-powerpoint ppt
-application/vnd.ms-project
-application/vnd.ms-tnef
-application/vnd.ms-works
-application/vnd.mseq
-application/vnd.msign
-application/vnd.music-niff
-application/vnd.musician
-application/vnd.netfpx
-application/vnd.noblenet-directory
-application/vnd.noblenet-sealer
-application/vnd.noblenet-web
-application/vnd.novadigm.EDM
-application/vnd.novadigm.EDX
-application/vnd.novadigm.EXT
-application/vnd.osa.netdeploy
-application/vnd.palm
-application/vnd.pg.format
-application/vnd.pg.osasli
-application/vnd.powerbuilder6
-application/vnd.powerbuilder6-s
-application/vnd.powerbuilder7
-application/vnd.powerbuilder7-s
-application/vnd.powerbuilder75
-application/vnd.powerbuilder75-s
-application/vnd.previewsystems.box
-application/vnd.publishare-delta-tree
-application/vnd.pvi.ptid1
-application/vnd.pwg-xhtml-print+xml
-application/vnd.rapid
-application/vnd.s3sms
-application/vnd.seemail
-application/vnd.shana.informed.formdata
-application/vnd.shana.informed.formtemplate
-application/vnd.shana.informed.interchange
-application/vnd.shana.informed.package
-application/vnd.sss-cod
-application/vnd.sss-dtf
-application/vnd.sss-ntf
-application/vnd.street-stream
-application/vnd.svd
-application/vnd.swiftview-ics
-application/vnd.triscape.mxs
-application/vnd.trueapp
-application/vnd.truedoc
-application/vnd.tve-trigger
-application/vnd.ufdl
-application/vnd.uplanet.alert
-application/vnd.uplanet.alert-wbxml
-application/vnd.uplanet.bearer-choice-wbxml
-application/vnd.uplanet.bearer-choice
-application/vnd.uplanet.cacheop
-application/vnd.uplanet.cacheop-wbxml
-application/vnd.uplanet.channel
-application/vnd.uplanet.channel-wbxml
-application/vnd.uplanet.list
-application/vnd.uplanet.list-wbxml
-application/vnd.uplanet.listcmd
-application/vnd.uplanet.listcmd-wbxml
-application/vnd.uplanet.signal
-application/vnd.vcx
-application/vnd.vectorworks
-application/vnd.vidsoft.vidconference
-application/vnd.visio
-application/vnd.vividence.scriptfile
-application/vnd.wap.sic
-application/vnd.wap.slc
-application/vnd.wap.wbxml wbxml
-application/vnd.wap.wmlc wmlc
-application/vnd.wap.wmlscriptc wmlsc
-application/vnd.webturbo
-application/vnd.wrq-hp3000-labelled
-application/vnd.wt.stf
-application/vnd.xara
-application/vnd.xfdl
-application/vnd.yellowriver-custom-menu
-application/whoispp-query
-application/whoispp-response
-application/wita
-application/wordperfect5.1
-application/x-bcpio bcpio
-application/x-cdlink vcd
-application/x-chess-pgn pgn
-application/x-compress
-application/x-cpio cpio
-application/x-csh csh
-application/x-director dcr dir dxr
-application/x-dvi dvi
-application/x-futuresplash spl
-application/x-gtar gtar
-application/x-gzip
-application/x-hdf hdf
-application/x-javascript js
-application/x-koan skp skd skt skm
-application/x-latex latex
-application/x-netcdf nc cdf
-application/x-sh sh
-application/x-shar shar
-application/x-shockwave-flash swf
-application/x-stuffit sit
-application/x-sv4cpio sv4cpio
-application/x-sv4crc sv4crc
-application/x-tar tar
-application/x-tcl tcl
-application/x-tex tex
-application/x-texinfo texinfo texi
-application/x-troff t tr roff
-application/x-troff-man man
-application/x-troff-me me
-application/x-troff-ms ms
-application/x-ustar ustar
-application/x-wais-source src
-application/x400-bp
-application/xml
-application/xml-dtd
-application/xml-external-parsed-entity
-application/zip zip
-audio/32kadpcm
-audio/basic au snd
-audio/g.722.1
-audio/l16
-audio/midi mid midi kar
-audio/mp4a-latm
-audio/mpa-robust
-audio/mpeg mpga mp2 mp3
-audio/parityfec
-audio/prs.sid
-audio/telephone-event
-audio/tone
-audio/vnd.cisco.nse
-audio/vnd.cns.anp1
-audio/vnd.cns.inf1
-audio/vnd.digital-winds
-audio/vnd.everad.plj
-audio/vnd.lucent.voice
-audio/vnd.nortel.vbk
-audio/vnd.nuera.ecelp4800
-audio/vnd.nuera.ecelp7470
-audio/vnd.nuera.ecelp9600
-audio/vnd.octel.sbc
-audio/vnd.qcelp
-audio/vnd.rhetorex.32kadpcm
-audio/vnd.vmx.cvsd
-audio/x-aiff aif aiff aifc
-audio/x-mpegurl m3u
-audio/x-pn-realaudio ram rm
-audio/x-pn-realaudio-plugin rpm
-audio/x-realaudio ra
-audio/x-wav wav
-chemical/x-pdb pdb
-chemical/x-xyz xyz
-image/bmp bmp
-image/cgm
-image/g3fax
-image/gif gif
-image/ief ief
-image/jpeg jpeg jpg jpe
-image/naplps
-image/png png
-image/prs.btif
-image/prs.pti
-image/tiff tiff tif
-image/vnd.cns.inf2
-image/vnd.dwg
-image/vnd.dxf
-image/vnd.fastbidsheet
-image/vnd.fpx
-image/vnd.fst
-image/vnd.fujixerox.edmics-mmr
-image/vnd.fujixerox.edmics-rlc
-image/vnd.mix
-image/vnd.net-fpx
-image/vnd.svf
-image/vnd.wap.wbmp wbmp
-image/vnd.xiff
-image/x-cmu-raster ras
-image/x-portable-anymap pnm
-image/x-portable-bitmap pbm
-image/x-portable-graymap pgm
-image/x-portable-pixmap ppm
-image/x-rgb rgb
-image/x-xbitmap xbm
-image/x-xpixmap xpm
-image/x-xwindowdump xwd
-message/delivery-status
-message/disposition-notification
-message/external-body
-message/http
-message/news
-message/partial
-message/rfc822
-message/s-http
-model/iges igs iges
-model/mesh msh mesh silo
-model/vnd.dwf
-model/vnd.flatland.3dml
-model/vnd.gdl
-model/vnd.gs-gdl
-model/vnd.gtw
-model/vnd.mts
-model/vnd.vtu
-model/vrml wrl vrml
-multipart/alternative
-multipart/appledouble
-multipart/byteranges
-multipart/digest
-multipart/encrypted
-multipart/form-data
-multipart/header-set
-multipart/mixed
-multipart/parallel
-multipart/related
-multipart/report
-multipart/signed
-multipart/voice-message
-text/calendar
-text/css css
-text/directory
-text/enriched
-text/html html htm
-text/parityfec
-text/plain asc txt
-text/prs.lines.tag
-text/rfc822-headers
-text/richtext rtx
-text/rtf rtf
-text/sgml sgml sgm
-text/tab-separated-values tsv
-text/t140
-text/uri-list
-text/vnd.DMClientScript
-text/vnd.IPTC.NITF
-text/vnd.IPTC.NewsML
-text/vnd.abc
-text/vnd.curl
-text/vnd.flatland.3dml
-text/vnd.fly
-text/vnd.fmi.flexstor
-text/vnd.in3d.3dml
-text/vnd.in3d.spot
-text/vnd.latex-z
-text/vnd.motorola.reflex
-text/vnd.ms-mediapackage
-text/vnd.wap.si
-text/vnd.wap.sl
-text/vnd.wap.wml wml
-text/vnd.wap.wmlscript wmls
-text/x-setext etx
-text/x-server-parsed-html shtml
-text/xml xml xsl
-text/xml-external-parsed-entity
-video/mp4v-es
-video/mpeg mpeg mpg mpe
-video/parityfec
-video/pointer
-video/quicktime qt mov
-video/vnd.fvt
-video/vnd.motorola.video
-video/vnd.motorola.videop
-video/vnd.mpegurl mxu
-video/vnd.mts
-video/vnd.nokia.interleaved-multimedia
-video/vnd.vivo
-video/x-msvideo avi
-video/x-sgi-movie movie
-x-conference/x-cooltalk ice
-
-
-
diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
deleted file mode 100644
index de49ceafd0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf
+++ /dev/null
@@ -1,66 +0,0 @@
-Port 8088
-#ServerName your.server.net
-SocketType ssl
-Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log
-ServerAdmin [email protected]
-ServerRoot /var/tmp/server_root
-ErrorLog logs/error_log_8088
-TransferLog logs/access_log_8088
-ErrorDiskLog logs/error_disk_log_8088
-ErrorDiskLogSize 200000 10
-TransferDiskLog logs/access_disk_log_8088
-TransferDiskLogSize 200000 10
-MaxClients 150
-DocumentRoot /var/tmp/server_root/htdocs
-DirectoryIndex index.html welcome.html
-DefaultType text/plain
-Alias /icons/ /var/tmp/server_root/icons/
-Alias /pics/ /var/tmp/server_root/icons/
-ScriptAlias /cgi-bin/ /var/tmp/server_root/cgi-bin/
-ScriptAlias /htbin/ /var/tmp/server_root/cgi-bin/
-ErlScriptAlias /cgi-bin/erl httpd_example io
-EvalScriptAlias /eval httpd_example io
-SSLCertificateFile /var/tmp/server_root/ssl/ssl_server.pem
-SSLCertificateKeyFile /var/tmp/server_root/ssl/ssl_server.pem
-SSLVerifyClient 0
-#Script HEAD /cgi-bin/printenv.sh
-#Action image/gif /cgi-bin/printenv.sh
-
-<Directory /var/tmp/server_root/htdocs/open>
-AuthName Open Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret>
-AuthName Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/secret/top_secret>
-AuthName Top Secret Area
-AuthUserFile /var/tmp/server_root/auth/passwd
-AuthGroupFile /var/tmp/server_root/auth/group
-require group group3
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_open>
-AuthName Open Area
-AuthMnesiaDB On
-require user one Aladdin
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret>
-AuthName Secret Area
-AuthMnesiaDB On
-require group group1 group2
-</Directory>
-
-<Directory /var/tmp/server_root/htdocs/mnesia_secret/top_secret>
-AuthName Top Secret Area
-AuthMnesiaDB On
-require group group3
-</Directory>
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
deleted file mode 100644
index 107e3ff610..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/config.shtml
+++ /dev/null
@@ -1,70 +0,0 @@
-<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
deleted file mode 100644
index a6e8a35a04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_open/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<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
deleted file mode 100644
index 016b04e540..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<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
deleted file mode 100644
index 34db3d5d1a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/dets_secret/top_secret/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<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
deleted file mode 100644
index 141db5be59..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/echo.shtml
+++ /dev/null
@@ -1,35 +0,0 @@
-<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
deleted file mode 100644
index 97333da898..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/exec.shtml
+++ /dev/null
@@ -1,30 +0,0 @@
-<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
deleted file mode 100644
index d54c36fe50..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/flastmod.shtml
+++ /dev/null
@@ -1,29 +0,0 @@
-<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
deleted file mode 100644
index 570ee9cf6d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/fsize.shtml
+++ /dev/null
@@ -1,29 +0,0 @@
-<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
deleted file mode 100644
index 529aad0437..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/include.shtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<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
deleted file mode 100644
index cfdc9f9ab7..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<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
deleted file mode 100644
index 65c1790813..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/last_modified.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<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
deleted file mode 100644
index d7953d5df4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/friedrich.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<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
deleted file mode 100644
index 506064bf04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/oech.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<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
deleted file mode 100644
index 8c17451f91..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/misc/welcome.html
+++ /dev/null
@@ -1 +0,0 @@
-<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
deleted file mode 100644
index a6e8a35a04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_open/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<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
deleted file mode 100644
index 016b04e540..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<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
deleted file mode 100644
index 2d17e8b596..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/mnesia_secret/top_secret/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<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
deleted file mode 100644
index a6e8a35a04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/open/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<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
deleted file mode 100644
index 016b04e540..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/dummy.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<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
deleted file mode 100644
index 34db3d5d1a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/htdocs/secret/top_secret/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<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/icons/README b/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README
deleted file mode 100644
index a1fc5a5a9c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/README
+++ /dev/null
@@ -1,161 +0,0 @@
-Public Domain Icons
-
- These icons were originally made for Mosaic for X and have been
- included in the NCSA httpd and Apache server distributions in the
- past. They are in the public domain and may be freely included in any
- application. The originals were done by Kevin Hughes ([email protected]).
-
- Many thanks to Andy Polyakov for tuning the icon colors and adding a
- few new images. If you'd like to contribute additions or ideas to
- this set, please let me know.
-
- The distribution site for these icons is at:
-
- http://www.eit.com/goodies/www.icons/
-
- Kevin Hughes
- September 11, 1995
-
-
-Suggested Uses
-
-The following are a few suggestions, to serve as a starting point for ideas.
-Please feel free to tweak and rename the icons as you like.
-
- a.gif
- This might be used to represent PostScript or text layout
- languages.
-
- alert.black.gif, alert.red.gif
- These can be used to highlight any important items, such as a
- README file in a directory.
-
- back.gif, forward.gif
- These can be used as links to go to previous and next areas.
-
- ball.gray.gif, ball.red.gif
- These might be used as bullets.
-
- binary.gif
- This can be used to represent binary files.
-
- binhex.gif
- This can represent BinHex-encoded data.
-
- blank.gif
- This can be used as a placeholder or a spacing element.
-
- bomb.gif
- This can be used to repreesnt core files.
-
- box1.gif, box2.gif
- These icons can be used to represent generic 3D applications and
- related files.
-
- broken.gif
- This can represent corrupted data.
-
- burst.gif
- This can call attention to new and important items.
-
- c.gif
- This might represent C source code.
-
- comp.blue.gif, comp.red.gif
- These little computer icons can stand for telnet or FTP
- sessions.
-
- compressed.gif
- This may represent compressed data.
-
- continued.gif
- This can be a link to a continued listing of a directory.
-
- down.gif, up.gif, left.gif, right.gif
- These can be used to scroll up, down, left and right in a
- listing or may be used to denote items in an outline.
-
- dvi.gif
- This can represent DVI files.
-
- f.gif
- This might represent FORTRAN or Forth source code.
-
- folder.gif, folder.open.gif, folder.sec.gif
- The folder can represent directories. There is also a version
- that can represent secure directories or directories that cannot
- be viewed.
-
- generic.gif, generic.sec.gif, generic.red.gif
- These can represent generic files, secure files, and important
- files, respectively.
-
- hand.right.gif, hand.up.gif
- These can point out important items (pun intended).
-
- image1.gif, image2.gif, image3.gif
- These can represent image formats of various types.
-
- index.gif
- This might represent a WAIS index or search facility.
-
- layout.gif
- This might represent files and formats that contain graphics as
- well as text layout, such as HTML and PDF files.
-
- link.gif
- This might represent files that are symbolic links.
-
- movie.gif
- This can represent various movie formats.
-
- p.gif
- This may stand for Perl or Python source code.
-
- pie0.gif ... pie8.gif
- These icons can be used in applications where a list of
- documents is returned from a search. The little pie chart images
- can denote how relevant the documents may be to your search
- query.
-
- patch.gif
- This may stand for patches and diff files.
-
- portal.gif
- This might be a link to an online service or a 3D world.
-
- ps.gif, quill.gif
- These may represent PostScript files.
-
- screw1.gif, screw2.gif
- These may represent CAD or engineering data and formats.
-
- script.gif
- This can represent any of various interpreted languages, such as
- Perl, python, TCL, and shell scripts, as well as server
- configuration files.
-
- sound1.gif, sound2.gif
- These can represent sound files.
-
- sphere1.gif, sphere2.gif
- These can represent 3D worlds or rendering applications and
- formats.
-
- tex.gif
- This can represent TeX files.
-
- text.gif
- This can represent generic (plain) text files.
-
- transfer.gif
- This can represent FTP transfers or uploads/downloads.
-
- unknown.gif
- This may represent a file of an unknown type.
-
- uuencoded.gif
- This can stand for uuencoded data.
-
- world1.gif, world2.gif
- These can represent 3D worlds or other 3D formats.
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
deleted file mode 100644
index bb23d971f4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/a.gif
+++ /dev/null
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
deleted file mode 100644
index eaecd2172a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.black.gif
+++ /dev/null
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
deleted file mode 100644
index a423894043..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/alert.red.gif
+++ /dev/null
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
deleted file mode 100644
index 3a1c139fc4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/apache_pb.gif
+++ /dev/null
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
deleted file mode 100644
index a694ae1ec3..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/back.gif
+++ /dev/null
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
deleted file mode 100644
index eb84268c4c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.gray.gif
+++ /dev/null
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
deleted file mode 100644
index a8425cb574..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ball.red.gif
+++ /dev/null
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
deleted file mode 100644
index 9a15cbae04..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binary.gif
+++ /dev/null
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
deleted file mode 100644
index 62d0363108..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/binhex.gif
+++ /dev/null
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
deleted file mode 100644
index 0ccf01e198..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/blank.gif
+++ /dev/null
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
deleted file mode 100644
index 270fdb1c06..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/bomb.gif
+++ /dev/null
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
deleted file mode 100644
index 65dcd002ea..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box1.gif
+++ /dev/null
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
deleted file mode 100644
index c43bc4faec..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/box2.gif
+++ /dev/null
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
deleted file mode 100644
index 9f8cbe9f76..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/broken.gif
+++ /dev/null
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
deleted file mode 100644
index fbdcf575f7..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/burst.gif
+++ /dev/null
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
deleted file mode 100644
index eb97cb7333..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button1.gif
+++ /dev/null
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
deleted file mode 100644
index fe0c97998c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button10.gif
+++ /dev/null
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
deleted file mode 100644
index 7698455bf9..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button2.gif
+++ /dev/null
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
deleted file mode 100644
index a8b8319232..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button3.gif
+++ /dev/null
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
deleted file mode 100644
index 0fd15a0d7f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button4.gif
+++ /dev/null
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
deleted file mode 100644
index 64241e5c5d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button5.gif
+++ /dev/null
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
deleted file mode 100644
index 867cfd1212..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button6.gif
+++ /dev/null
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
deleted file mode 100644
index b3f5fb248f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button7.gif
+++ /dev/null
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
deleted file mode 100644
index 7a308be8f6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button8.gif
+++ /dev/null
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
deleted file mode 100644
index 9acba576c0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/button9.gif
+++ /dev/null
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
deleted file mode 100644
index 3883088e7a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonl.gif
+++ /dev/null
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
deleted file mode 100644
index c4dc3887db..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/buttonr.gif
+++ /dev/null
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
deleted file mode 100644
index 7555b6c164..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/c.gif
+++ /dev/null
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
deleted file mode 100644
index f8d76a8c23..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.blue.gif
+++ /dev/null
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
deleted file mode 100644
index 7664cd0364..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/comp.gray.gif
+++ /dev/null
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
deleted file mode 100644
index 39e732739f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/compressed.gif
+++ /dev/null
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
deleted file mode 100644
index b0ffb7e0cc..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/continued.gif
+++ /dev/null
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
deleted file mode 100644
index 48264601ae..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dir.gif
+++ /dev/null
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
deleted file mode 100644
index a354c871cd..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/down.gif
+++ /dev/null
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
deleted file mode 100644
index 791be33105..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/dvi.gif
+++ /dev/null
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
deleted file mode 100644
index fbe353c282..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/f.gif
+++ /dev/null
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
deleted file mode 100644
index 48264601ae..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.gif
+++ /dev/null
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
deleted file mode 100644
index 30979cb528..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.open.gif
+++ /dev/null
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
deleted file mode 100644
index 75332d9e59..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/folder.sec.gif
+++ /dev/null
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
deleted file mode 100644
index b2959b4c85..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/forward.gif
+++ /dev/null
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
deleted file mode 100644
index de60b2940f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.gif
+++ /dev/null
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
deleted file mode 100644
index 94743981d9..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.red.gif
+++ /dev/null
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
deleted file mode 100644
index 88d5240c3c..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/generic.sec.gif
+++ /dev/null
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
deleted file mode 100644
index 5cdbc7206d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.right.gif
+++ /dev/null
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
deleted file mode 100644
index 85a5d68317..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/hand.up.gif
+++ /dev/null
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
deleted file mode 100644
index 35443fb63a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/htdig.gif
+++ /dev/null
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
deleted file mode 100644
index ad1686e448..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/icon.sheet.gif
+++ /dev/null
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
deleted file mode 100644
index 01e442bfa9..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image1.gif
+++ /dev/null
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
deleted file mode 100644
index 751faeea36..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image2.gif
+++ /dev/null
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
deleted file mode 100644
index 4f30484ff6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/image3.gif
+++ /dev/null
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
deleted file mode 100644
index 162478fb3a..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/index.gif
+++ /dev/null
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
deleted file mode 100644
index c96338a152..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/layout.gif
+++ /dev/null
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
deleted file mode 100644
index 279e6710d4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/left.gif
+++ /dev/null
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
deleted file mode 100644
index c5b6889a76..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/link.gif
+++ /dev/null
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
deleted file mode 100644
index 0035183774..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/movie.gif
+++ /dev/null
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
deleted file mode 100644
index 7b917b4e91..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/p.gif
+++ /dev/null
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
deleted file mode 100644
index 39bc90e795..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/patch.gif
+++ /dev/null
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
deleted file mode 100644
index c88fd777c4..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pdf.gif
+++ /dev/null
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
deleted file mode 100644
index 6f7a0ae7a7..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie0.gif
+++ /dev/null
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
deleted file mode 100644
index 03aa6be71e..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie1.gif
+++ /dev/null
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
deleted file mode 100644
index b04c5e0908..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie2.gif
+++ /dev/null
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
deleted file mode 100644
index 4db9d023ed..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie3.gif
+++ /dev/null
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
deleted file mode 100644
index 93471fdd88..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie4.gif
+++ /dev/null
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
deleted file mode 100644
index 57aee93f07..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie5.gif
+++ /dev/null
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
deleted file mode 100644
index 0dc327b569..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie6.gif
+++ /dev/null
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
deleted file mode 100644
index 8661337f06..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie7.gif
+++ /dev/null
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
deleted file mode 100644
index 59ddb34ce0..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/pie8.gif
+++ /dev/null
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
deleted file mode 100644
index 0e6e506e00..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/portal.gif
+++ /dev/null
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
deleted file mode 100644
index d324ab80ea..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/poweredby.gif
+++ /dev/null
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
deleted file mode 100644
index 0f565bc1db..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/ps.gif
+++ /dev/null
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
deleted file mode 100644
index 818a5cdc7e..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/quill.gif
+++ /dev/null
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
deleted file mode 100644
index b256e5f75f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/right.gif
+++ /dev/null
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
deleted file mode 100644
index af6ba2b097..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw1.gif
+++ /dev/null
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
deleted file mode 100644
index 06dccb3e44..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/screw2.gif
+++ /dev/null
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
deleted file mode 100644
index d8a853bc58..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/script.gif
+++ /dev/null
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
deleted file mode 100644
index 8efb49f55d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound1.gif
+++ /dev/null
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
deleted file mode 100644
index 48e6a7fb2f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sound2.gif
+++ /dev/null
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
deleted file mode 100644
index 7067070da2..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere1.gif
+++ /dev/null
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
deleted file mode 100644
index a9e462a377..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/sphere2.gif
+++ /dev/null
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
deleted file mode 100644
index 4cfe0a5e0f..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star.gif
+++ /dev/null
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
deleted file mode 100644
index a0c83cb85b..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/star_blank.gif
+++ /dev/null
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
deleted file mode 100644
index 617e779efa..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tar.gif
+++ /dev/null
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
deleted file mode 100644
index 45e43233b8..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/tex.gif
+++ /dev/null
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
deleted file mode 100644
index 4c623909fb..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/text.gif
+++ /dev/null
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
deleted file mode 100644
index 33697dbb66..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/transfer.gif
+++ /dev/null
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
deleted file mode 100644
index 32b1ea23fb..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/unknown.gif
+++ /dev/null
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
deleted file mode 100644
index 6d6d6d1ebf..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/up.gif
+++ /dev/null
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
deleted file mode 100644
index 4387d529f6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uu.gif
+++ /dev/null
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
deleted file mode 100644
index 4387d529f6..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/uuencoded.gif
+++ /dev/null
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
deleted file mode 100644
index 05b4ec2058..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world1.gif
+++ /dev/null
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
deleted file mode 100644
index e3203f7a88..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/icons/world2.gif
+++ /dev/null
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
deleted file mode 100644
index 8d1c8b69c3..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/logs/Dummy_File_Needed_By_WinZip
+++ /dev/null
@@ -1 +0,0 @@
-
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
deleted file mode 100644
index 427447958d..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_client.pem
+++ /dev/null
@@ -1,31 +0,0 @@
------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
deleted file mode 100644
index 4aac86db49..0000000000
--- a/lib/inets/test/old_httpd_SUITE_data/server_root/ssl/ssl_server.pem
+++ /dev/null
@@ -1,31 +0,0 @@
------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/vsn.mk b/lib/inets/vsn.mk
index 560d524bac..05cf4f6cc3 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.4.4
+INETS_VSN = 6.4.5
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index b44a04d7cd..346d467c2d 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.8</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/jinterface/java_src/pom.xml.src b/lib/jinterface/java_src/pom.xml.src
index 98232db78c..584bd81076 100644
--- a/lib/jinterface/java_src/pom.xml.src
+++ b/lib/jinterface/java_src/pom.xml.src
@@ -76,6 +76,17 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Automatic-Module-Name>com.ericsson.otp.erlang</Automatic-Module-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index 373e2dab22..0a8a1190ec 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1 +1 @@
-JINTERFACE_VSN = 1.8
+JINTERFACE_VSN = 1.8.1
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 94c8fb9e20..a30d28d55a 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -56,7 +56,7 @@ $ <input>erl -sname foobar</input></pre>
<p>Normally, connections are established automatically when
another node is referenced. This functionality can be disabled
by setting Kernel configuration parameter
- <c>dist_auto_connect</c> to <c>false</c>, see
+ <c>dist_auto_connect</c> to <c>never</c>, see
<seealso marker="kernel_app"><c>kernel(6)</c></seealso>. In this case,
connections must be established explicitly by calling
<seealso marker="#connect_node/1"><c>connect_node/1</c></seealso>.</p>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index a5316dd476..d7f224c38e 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 5.4.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Refactored an internal API.</p>
+ <p>
+ Own Id: OTP-14784</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 5.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 4a713b2a99..0bc9f121a0 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -106,6 +106,7 @@ MODULES = \
inet_sctp \
kernel \
kernel_config \
+ kernel_refc \
local_udp \
local_tcp \
net \
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index 2b35d2acfb..34d5497a4a 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -68,7 +68,8 @@ do_start(Spawn, Owner, FileName, ModeList) ->
erlang:dt_restore_tag(Utag),
%% process_flag(trap_exit, true),
case parse_options(ModeList) of
- {ReadMode, UnicodeMode, Opts} ->
+ {ReadMode, UnicodeMode, Opts0} ->
+ Opts = maybe_add_read_ahead(ReadMode, Opts0),
case raw_file_io:open(FileName, [raw | Opts]) of
{error, Reason} = Error ->
Self ! {Ref, Error},
@@ -158,6 +159,24 @@ valid_enc({utf32,little}) ->
valid_enc(_Other) ->
{error,badarg}.
+%% Add a small read_ahead buffer if the file is opened for reading
+%% only in list mode and no read_ahead is already given.
+maybe_add_read_ahead(binary, Opts) ->
+ Opts;
+maybe_add_read_ahead(list, Opts) ->
+ P = fun(read_ahead) -> true;
+ ({read_ahead,_}) -> true;
+ (append) -> true;
+ (exclusive) -> true;
+ (write) -> true;
+ (_) -> false
+ end,
+ case lists:any(P, Opts) of
+ false ->
+ [{read_ahead, 4096}|Opts];
+ true ->
+ Opts
+ end.
server_loop(#state{mref = Mref} = State) ->
receive
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index e4852a6e75..82a3571da9 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -57,6 +57,7 @@
inet_tcp_dist,
kernel,
kernel_config,
+ kernel_refc,
local_tcp,
local_udp,
net,
@@ -114,6 +115,7 @@
heart,
init,
kernel_config,
+ kernel_refc,
kernel_sup,
net_kernel,
net_sup,
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index cba57088ec..0382764b39 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -111,6 +111,13 @@ init([]) ->
type => worker,
modules => [kernel_config]},
+ RefC = #{id => kernel_refc,
+ start => {kernel_refc, start_link, []},
+ restart => permanent,
+ shutdown => 2000,
+ type => worker,
+ modules => [kernel_refc]},
+
Code = #{id => code_server,
start => {code, start_link, []},
restart => permanent,
@@ -148,7 +155,7 @@ init([]) ->
case init:get_argument(mode) of
{ok, [["minimal"]]} ->
- {ok, {SupFlags, [Code, File, StdError, User, Config, SafeSup]}};
+ {ok, {SupFlags, [Code, File, StdError, User, Config, RefC, SafeSup]}};
_ ->
Rpc = #{id => rex,
start => {rpc, start_link, []},
@@ -199,7 +206,7 @@ init([]) ->
{ok, {SupFlags,
[Code, Rpc, Global, InetDb | DistAC] ++
[NetSup, GlGroup, File, SigSrv,
- StdError, User, Config, SafeSup] ++ Timer}}
+ StdError, User, Config, RefC, SafeSup] ++ Timer}}
end;
init(safe) ->
SupFlags = #{strategy => one_for_one,
diff --git a/lib/kernel/src/kernel_refc.erl b/lib/kernel/src/kernel_refc.erl
new file mode 100644
index 0000000000..05076dc885
--- /dev/null
+++ b/lib/kernel/src/kernel_refc.erl
@@ -0,0 +1,139 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(kernel_refc).
+
+-behaviour(gen_server).
+
+%% External exports
+-export([start_link/0, scheduler_wall_time/1]).
+%% Internal exports
+-export([init/1, handle_info/2, terminate/2]).
+-export([handle_call/3, handle_cast/2, code_change/3]).
+
+%%%-----------------------------------------------------------------
+%%% This module implements a process that handles reference counters for
+%%% various erts or other kernel resources which needs reference counting.
+%%%
+%%% Should not be documented nor used directly by user applications.
+%%%-----------------------------------------------------------------
+start_link() ->
+ gen_server:start_link({local,kernel_refc}, kernel_refc, [], []).
+
+-spec scheduler_wall_time(boolean()) -> boolean().
+scheduler_wall_time(Bool) ->
+ gen_server:call(kernel_refc, {scheduler_wall_time, self(), Bool}, infinity).
+
+%%-----------------------------------------------------------------
+%% Callback functions from gen_server
+%%-----------------------------------------------------------------
+
+-spec init([]) -> {'ok', map()} | {'stop', term()}.
+
+init([]) ->
+ resource(scheduler_wall_time, false),
+ {ok, #{scheduler_wall_time=>#{}}}.
+
+-spec handle_call(term(), term(), State) -> {'reply', term(), State}.
+handle_call({What, Who, false}, _From, State) ->
+ {Reply, Cnt} = do_stop(What, maps:get(What, State), Who),
+ {reply, Reply, State#{What:=Cnt}};
+handle_call({What, Who, true}, _From, State) ->
+ {Reply, Cnt} = do_start(What, maps:get(What, State), Who),
+ {reply, Reply, State#{What:=Cnt}};
+handle_call(_, _From, State) ->
+ {reply, badarg, State}.
+
+-spec handle_cast(term(), State) -> {'noreply', State}.
+handle_cast(_, State) ->
+ {noreply, State}.
+
+-spec handle_info(term(), State) -> {'noreply', State}.
+handle_info({'DOWN', _Ref, process, Pid, _}, State) ->
+ Cleanup = fun(Resource, Cnts) ->
+ cleanup(Resource, Cnts, Pid)
+ end,
+ {noreply, maps:map(Cleanup, State)};
+handle_info(_, State) ->
+ {noreply, State}.
+
+-spec terminate(term(), term()) -> 'ok'.
+terminate(_Reason, _State) ->
+ ok.
+
+-spec code_change(term(), State, term()) -> {'ok', State}.
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%-----------------------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------------------
+
+do_start(Resource, Cnt, Pid) ->
+ case maps:get(Pid, Cnt, undefined) of
+ undefined ->
+ Ref = erlang:monitor(process, Pid),
+ case any(Cnt) of
+ true ->
+ {true, Cnt#{Pid=>{1, Ref}}};
+ false ->
+ resource(Resource, true),
+ {false, Cnt#{Pid=>{1, Ref}}}
+ end;
+ {N, Ref} ->
+ {true, Cnt#{Pid=>{N+1, Ref}}}
+ end.
+
+do_stop(Resource, Cnt0, Pid) ->
+ case maps:get(Pid, Cnt0, undefined) of
+ undefined ->
+ {any(Cnt0), Cnt0};
+ {1, Ref} ->
+ erlang:demonitor(Ref, [flush]),
+ Cnt = maps:remove(Pid, Cnt0),
+ case any(Cnt) of
+ true ->
+ {true, Cnt};
+ false ->
+ resource(Resource, false),
+ {true, Cnt}
+ end;
+ {N, Ref} ->
+ {true, Cnt0#{Pid=>{N-1, Ref}}}
+ end.
+
+cleanup(Resource, Cnt0, Pid) ->
+ case maps:is_key(Pid, Cnt0) of
+ true ->
+ Cnt = maps:remove(Pid, Cnt0),
+ case any(Cnt) of
+ true ->
+ Cnt;
+ false ->
+ resource(Resource, false),
+ Cnt
+ end;
+ false ->
+ Cnt0
+ end.
+
+any(Cnt) -> maps:size(Cnt) > 0.
+
+resource(scheduler_wall_time, Enable) ->
+ _ = erts_internal:scheduler_wall_time(Enable).
diff --git a/lib/kernel/test/kernel_SUITE.erl b/lib/kernel/test/kernel_SUITE.erl
index da56359294..7898988dbe 100644
--- a/lib/kernel/test/kernel_SUITE.erl
+++ b/lib/kernel/test/kernel_SUITE.erl
@@ -30,14 +30,14 @@
-export([init_per_testcase/2, end_per_testcase/2]).
%% Test cases must be exported.
--export([app_test/1, appup_test/1]).
+-export([app_test/1, appup_test/1, refc/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,2}}].
all() ->
- [app_test, appup_test].
+ [app_test, appup_test, refc].
groups() ->
[].
@@ -163,3 +163,68 @@ check_appup([Vsn|Vsns],Instrs,Expected) ->
end;
check_appup([],_,_) ->
ok.
+
+%%% Check that refc module handles the counters as expected
+refc(_Config) ->
+ Enable = fun(Enable) -> erlang:system_flag(scheduler_wall_time, Enable) end,
+ IsOn = fun() -> undefined /= erlang:statistics(scheduler_wall_time) end,
+ Tester = self(),
+ Loop = fun Loop() ->
+ receive
+ die -> normal;
+ {apply, Bool} ->
+ Res = Enable(Bool),
+ Tester ! {self(), Res},
+ Loop()
+ end
+ end,
+
+ %% Counter should be 0
+ false = Enable(false),
+
+ false = Enable(true),
+ true = Enable(true),
+ true = Enable(false),
+ true = Enable(false),
+
+ %% Counter should be 0
+ false = IsOn(),
+
+ P1 = spawn_link(Loop),
+ P1 ! {apply, true},
+ receive {P1, R1} -> false = R1 end,
+
+ %% P1 has turned it on counter should be one
+ true = IsOn(),
+ true = Enable(true),
+ true = Enable(false),
+ true = IsOn(),
+
+ P1 ! {apply, false},
+ receive {P1, R2} -> true = R2 end,
+ false = IsOn(),
+
+ P1 ! {apply, true},
+ receive {P1, R3} -> false = R3 end,
+ true = IsOn(),
+ true = Enable(false),
+
+
+ P1 ! die,
+ timer:sleep(100),
+ false = IsOn(),
+ false = Enable(false),
+
+ P2 = spawn_link(Loop),
+ P2 ! {apply, true},
+ receive {P2, R4} -> false = R4 end,
+ true = IsOn(),
+ P2 ! {apply, true},
+ receive {P2, R5} -> true = R5 end,
+ true = IsOn(),
+
+ P2 ! die,
+ timer:sleep(100),
+ false = IsOn(),
+
+ ok.
diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl
index db753679ea..ab62f4dc34 100644
--- a/lib/kernel/test/prim_file_SUITE.erl
+++ b/lib/kernel/test/prim_file_SUITE.erl
@@ -1787,12 +1787,25 @@ free_memory() ->
{value, {buffered_memory, Buffed}} -> Buffed;
false -> 0
end),
- TotFree div (1024*1024)
+ usable_mem(TotFree) div (1024*1024)
catch
error : undef ->
ct:fail({"os_mon not built"})
end.
+usable_mem(Memory) ->
+ case test_server:is_valgrind() of
+ true ->
+ %% Valgrind uses extra memory for the V- and A-bits.
+ %% http://valgrind.org/docs/manual/mc-manual.html#mc-manual.value
+ %% Docs says it uses "compression to represent the V bits compactly"
+ %% but let's be conservative and cut usable memory in half.
+ Memory div 2;
+ false ->
+ Memory
+ end.
+
+
%%%-----------------------------------------------------------------
%%% Utilities
rm_rf(Mod,Dir) ->
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index cef54dd41a..106bda01ca 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 5.4
+KERNEL_VSN = 5.4.1
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index deb2bfcff3..54e048a172 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -37,7 +37,22 @@
section is the version number of Megaco.</p>
- <section><title>Megaco 3.18.2</title>
+ <section><title>Megaco 3.18.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 3.18.2</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index 9c6ba5bba0..a4f7de7f07 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.18.2
+MEGACO_VSN = 3.18.3
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 026c6a89d7..ba94e913f5 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -39,7 +39,49 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.15.1</title>
+ <section><title>Mnesia 4.15.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed a quadratic behavior in startup. This change
+ implies that backend plugins (if used) must be set when
+ the schema is created or via configuration parameters
+ before mnesia is started.</p>
+ <p>
+ Own Id: OTP-14829 Aux Id: ERIERL-84 </p>
+ </item>
+ <item>
+ <p>
+ Bad timing could crash mnesia after a checkpoint was
+ deactivated and reactivated with the same checkpoint name
+ on different tables.</p>
+ <p>
+ Own Id: OTP-14841 Aux Id: ERIERL-113 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix backup error handling, the real failure reason was
+ not returned.</p>
+ <p>
+ Own Id: OTP-14776 Aux Id: ERIERL-103 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.1</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/mnesia/src/mnesia_checkpoint.erl b/lib/mnesia/src/mnesia_checkpoint.erl
index 2ff77326a9..8112378ffd 100644
--- a/lib/mnesia/src/mnesia_checkpoint.erl
+++ b/lib/mnesia/src/mnesia_checkpoint.erl
@@ -857,9 +857,9 @@ retainer_loop(Cp = #checkpoint_args{is_activated=false, name=Name}) ->
retainer_loop(Cp = #checkpoint_args{name=Name}) ->
receive
{_From, {retain, Tid, Tab, Key, OldRecs}} ->
- R = val({Tab, {retainer, Name}}),
+ R = ?catch_val({Tab, {retainer, Name}}),
PendingTab = Cp#checkpoint_args.pending_tab,
- case R#retainer.really_retain of
+ case is_record(R, retainer) andalso R#retainer.really_retain of
true ->
Store = R#retainer.store,
try true = ets:member(PendingTab, Tid),
diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl
index 83cc19c678..71952af31c 100644
--- a/lib/mnesia/src/mnesia_schema.erl
+++ b/lib/mnesia/src/mnesia_schema.erl
@@ -952,19 +952,9 @@ get_index_plugins() ->
get_schema_user_property(mnesia_index_plugins).
get_schema_user_property(Key) ->
- Tab = schema,
- %% Must work reliably both within transactions and outside of transactions
- Res = case get(mnesia_activity_state) of
- undefined ->
- dirty_read_table_property(Tab, Key);
- _ ->
- do_read_table_property(Tab, Key)
- end,
- case Res of
- undefined ->
- [];
- {_, Types} ->
- Types
+ case dirty_read_table_property(schema, Key) of
+ undefined -> [];
+ {_, Types} -> Types
end.
get_ext_types_disc() ->
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index a95f468ba2..45f811846d 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.15.1
+MNESIA_VSN = 4.15.3
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index 05ea550964..96cd89b375 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -32,6 +32,73 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug introduced in OTP-20 would make Crashdump Viewer
+ crash when trying to expand an empty binary. This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-14642</p>
+ </item>
+ <item>
+ <p>
+ If a match spec in the config file contained more than
+ one clause, observer would earlier crash when trying to
+ display it in the GUI. This is now corrected.</p>
+ <p>
+ Own Id: OTP-14643 Aux Id: ERL-489 </p>
+ </item>
+ <item>
+ <p>Writing of crash dumps is significantly faster.</p>
+ <p>Maps are now included in crash dumps.</p>
+ <p>Constants terms would only be shown in one process,
+ while other processes referencing the same constant term
+ would show a marker for incomplete heap. </p>
+ <p>
+ Own Id: OTP-14685 Aux Id: OTP-14611, OTP-14603, OTP-14595 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Binaries and some other data in crash dumps are now
+ encoded in base64 (instead of in hex), which will reduce
+ the size of crash dumps.</p>
+ <p>A few bugs in the handling of sub binaries in
+ <c>crashdump_viewer</c> have been fixed.</p>
+ <p>
+ Own Id: OTP-14686</p>
+ </item>
+ <item>
+ <p>
+ In order to allow future improvements, Crashdump Viewer
+ now checks the version tag of the crashdump to see that
+ it is a known format. If the crashdump version is newer
+ than Crashdump Viewer is prepared to read, then an
+ information dialog is displayed before Crashdump Viewer
+ terminates.</p>
+ <p>
+ If an incomplete process heap is discovered in a
+ crashdump, Crashdump Viewer will now display a warning
+ for this, similar to the warning displayed when a
+ crashdump is truncated. Incomplete heaps can occur if for
+ instance the literals are not included, which is the case
+ for all dumps prior to OTP-20.2.</p>
+ <p>
+ Own Id: OTP-14755</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 2.5</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index 5f43198f85..fc1fca0925 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 2.5
+OBSERVER_VSN = 2.6
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index 6a8b0485eb..2aa55ca99c 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -32,7 +32,22 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.12</title>
+ <section><title>ODBC 2.12.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 2e313570e1..3f7677a71d 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.12
+ODBC_VSN = 2.12.1
diff --git a/lib/orber/doc/src/notes.xml b/lib/orber/doc/src/notes.xml
index 5a82270b28..35da4f73da 100644
--- a/lib/orber/doc/src/notes.xml
+++ b/lib/orber/doc/src/notes.xml
@@ -33,7 +33,28 @@
<file>notes.xml</file>
</header>
- <section><title>Orber 3.8.3</title>
+ <section><title>Orber 3.8.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ <item>
+ <p> Removed the man warnings by using the code tag
+ instead of c tag. </p>
+ <p>
+ Own Id: OTP-14673</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Orber 3.8.3</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/orber/vsn.mk b/lib/orber/vsn.mk
index 595e686cb7..bfd3f283b5 100644
--- a/lib/orber/vsn.mk
+++ b/lib/orber/vsn.mk
@@ -1 +1 @@
-ORBER_VSN = 3.8.3
+ORBER_VSN = 3.8.4
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index b29a64155e..cec0856a8b 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.4.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.4.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index e4250f577b..eb4f13ea9e 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.4.3
+OS_MON_VSN = 2.4.4
diff --git a/lib/otp_mibs/doc/src/notes.xml b/lib/otp_mibs/doc/src/notes.xml
index dbd2f47ffb..c99148a904 100644
--- a/lib/otp_mibs/doc/src/notes.xml
+++ b/lib/otp_mibs/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the OTP_Mibs
application.</p>
+<section><title>Otp_Mibs 1.1.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Otp_Mibs 1.1.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/otp_mibs/vsn.mk b/lib/otp_mibs/vsn.mk
index 7a793007ee..13406cb5b1 100644
--- a/lib/otp_mibs/vsn.mk
+++ b/lib/otp_mibs/vsn.mk
@@ -1,4 +1,4 @@
-OTP_MIBS_VSN = 1.1.1
+OTP_MIBS_VSN = 1.1.2
# Note: The branch 'otp_mibs' is defunct as of otp_mibs-1.0.4 and
# should NOT be used again.
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 3fa7169f50..b3370a06ab 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Warnings about unused functions in <c>leexinc.hrl</c>
+ are suppressed. </p>
+ <p>
+ Own Id: OTP-14697</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 502ca00a47..b6d2ce0cd4 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.1.5
+PARSETOOLS_VSN = 2.1.6
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index a4c0194328..11012ee9e5 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -35,6 +35,31 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a bug in <c>public_key:ssh_encode/2</c> that made
+ it possible to erroneously encode e.g. an RSA key with
+ another type e.g. ECDSA in the resulting binary.</p>
+ <p>
+ Own Id: OTP-14570 Aux Id: ERIERL-52, OTP-14676 </p>
+ </item>
+ <item>
+ <p>
+ Corrected handling of parameterized EC keys in
+ public_key:generate_key/1 so that it will work as
+ expected instead of causing a runtime error in crypto.</p>
+ <p>
+ Own Id: OTP-14620</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.5.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index c01d8820f2..99a0cc087e 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.5.1
+PUBLIC_KEY_VSN = 1.5.2
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 8b4d437c26..93e3e26fda 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.12.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.12.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index 1b075a507d..a1edde8516 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -293,7 +293,7 @@ fetch_stats_loop(Parent, Time) ->
erlang:system_flag(scheduler_wall_time, true),
receive
_Msg ->
- %% erlang:system_flag(scheduler_wall_time, false)
+ erlang:system_flag(scheduler_wall_time, false),
ok
after Time ->
_M = Parent ! {stats, 1,
@@ -340,7 +340,6 @@ etop_collect(Collector) ->
case SchedulerWallTime of
undefined ->
- erlang:system_flag(scheduler_wall_time,true),
spawn(fun() -> flag_holder_proc(Collector) end),
ok;
_ ->
@@ -348,10 +347,11 @@ etop_collect(Collector) ->
end.
flag_holder_proc(Collector) ->
+ erlang:system_flag(scheduler_wall_time,true),
Ref = erlang:monitor(process,Collector),
receive
{'DOWN',Ref,_,_,_} ->
- %% erlang:system_flag(scheduler_wall_time,false)
+ erlang:system_flag(scheduler_wall_time,false),
ok
end.
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index d8a4ede136..872bd5db1d 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.12.2
+RUNTIME_TOOLS_VSN = 1.12.3
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index b144122c4b..e532c3cd6f 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -31,6 +31,26 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 3.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The Report Browser, rb, could earlier not handle reports
+ that were not lists, for example generated by
+ <c>error_logger:info_report({some, tuple})</c>. This term
+ is allowed as input to error_logger, but rb would state
+ that "A report on bad form was encountered". This is now
+ corrected.</p>
+ <p>
+ Own Id: OTP-13906 Aux Id: ERL-261 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 3.1</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl
index 4935782cf2..824820c214 100644
--- a/lib/sasl/test/release_handler_SUITE.erl
+++ b/lib/sasl/test/release_handler_SUITE.erl
@@ -22,7 +22,8 @@
-include_lib("common_test/include/ct.hrl").
-include("test_lib.hrl").
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
+-export([scheduler_wall_time/0, garbage_collect/0]). %% rpc'ed
% Default timetrap timeout (set in init_per_testcase).
%-define(default_timeout, ?t:minutes(40)).
@@ -1085,8 +1086,9 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
Rel2Dir = filename:dirname(Rel2),
%% Start a slave node
+ PA = filename:dirname(code:which(?MODULE)),
{ok, Node} = t_start_node(otp_9395_update_many_mods, Rel1,
- filename:join(Rel1Dir,"sys.config")),
+ filename:join(Rel1Dir,"sys.config"), "-pa " ++ PA),
%% Start a lot of processes on the new node, all with refs to each
%% module that will be updated
@@ -1109,8 +1111,8 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
[RelVsn2, filename:join(Rel2Dir, "sys.config")]),
%% First, install release directly and check how much time it takes
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ SWTFlag0 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst0,{ok, _, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT0 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1135,9 +1137,9 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
%% Finally install release after check and purge, and check that
%% this install was faster than the first.
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,false]),
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ SWTFlag0 ! die,
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ _SWTFlag1 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst2,{ok, _RelVsn1, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT2 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1161,6 +1163,15 @@ otp_9395_update_many_mods(Conf) when is_list(Conf) ->
ok.
+scheduler_wall_time() ->
+ erlang:system_flag(scheduler_wall_time,true),
+ receive _Msg -> normal end.
+
+garbage_collect() ->
+ Pids = processes(),
+ [erlang:garbage_collect(Pid) || Pid <- Pids].
+
+
otp_9395_update_many_mods(cleanup,_Conf) ->
stop_node(node_name(otp_9395_update_many_mods)).
@@ -1190,8 +1201,9 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
Rel2Dir = filename:dirname(Rel2),
%% Start a slave node
+ PA = filename:dirname(code:which(?MODULE)),
{ok, Node} = t_start_node(otp_9395_rm_many_mods, Rel1,
- filename:join(Rel1Dir,"sys.config")),
+ filename:join(Rel1Dir,"sys.config"), "-pa " ++ PA),
%% Start a lot of processes on the new node, all with refs to each
%% module that will be updated
@@ -1214,8 +1226,8 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
[RelVsn2, filename:join(Rel2Dir, "sys.config")]),
%% First, install release directly and check how much time it takes
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ SWTFlag0 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst0,{ok, _, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT0 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
@@ -1240,9 +1252,9 @@ otp_9395_rm_many_mods(Conf) when is_list(Conf) ->
%% Finally install release after check and purge, and check that
%% this install was faster than the first.
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,false]),
- rpc:call(Node,erlang,garbage_collect,[]),
- rpc:call(Node,erlang,system_flag,[scheduler_wall_time,true]),
+ SWTFlag0 ! die,
+ rpc:call(Node,?MODULE,garbage_collect,[]),
+ _SWTFlag1 = spawn_link(Node, ?MODULE, scheduler_wall_time, []),
{TInst2,{ok, _RelVsn1, []}} =
timer:tc(rpc,call,[Node, release_handler, install_release, [RelVsn2]]),
SWT2 = rpc:call(Node,erlang,statistics,[scheduler_wall_time]),
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index e980a42688..2488197ec5 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 3.1
+SASL_VSN = 3.1.1
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 6bdcae5dd7..1b5f94ed07 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -34,7 +34,22 @@
</header>
- <section><title>SNMP 5.2.8</title>
+ <section><title>SNMP 5.2.9</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index ef48608bda..c195f9f5d9 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 5.2.8
+SNMP_VSN = 5.2.9
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index c9e153f30c..3a2f55a487 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -30,6 +30,65 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.6.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix problem with OpenSSH 7.2 (and later) clients that has
+ used sha1 instead of sha2 for rsa-sha-256/512 user's
+ public keys.</p>
+ <p>
+ Own Id: OTP-14827 Aux Id: ERL-531 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Ssh 4.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Passphrase option for ecdsa public keys was missing.</p>
+ <p>
+ Own Id: OTP-14602</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The host and user public key handling is hardened so that
+ a faulty plugin can't deliver a key of wrong type.</p>
+ <p>
+ Better checks in the server of the available hostkey's
+ types at start and at each accept.</p>
+ <p>
+ Better checks in the client of the available user public
+ key types at connect.</p>
+ <p>
+ Own Id: OTP-14676 Aux Id: ERIERL-52, OTP-14570 </p>
+ </item>
+ <item>
+ <p>
+ SSH can now fetch the host key from the private keys
+ stored in an Engine. See the crypto application for
+ details about Engines.</p>
+ <p>
+ Own Id: OTP-14757</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.6.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssh/src/ssh.app.src b/lib/ssh/src/ssh.app.src
index 974292fde1..4a22322333 100644
--- a/lib/ssh/src/ssh.app.src
+++ b/lib/ssh/src/ssh.app.src
@@ -42,10 +42,10 @@
{env, []},
{mod, {ssh_app, []}},
{runtime_dependencies, [
- "crypto-3.7.3",
+ "crypto-4.2",
"erts-6.0",
"kernel-3.0",
- "public_key-1.4",
+ "public_key-1.5.2",
"stdlib-3.3"
]}]}.
diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl
index 894877f8bf..03d264745b 100644
--- a/lib/ssh/src/ssh_auth.erl
+++ b/lib/ssh/src/ssh_auth.erl
@@ -304,11 +304,10 @@ handle_userauth_request(#ssh_msg_userauth_request{user = User,
SigWLen/binary>>
},
SessionId,
- #ssh{opts = Opts,
- userauth_supported_methods = Methods} = Ssh) ->
+ #ssh{userauth_supported_methods = Methods} = Ssh) ->
case verify_sig(SessionId, User, "ssh-connection",
- BAlg, KeyBlob, SigWLen, Opts) of
+ BAlg, KeyBlob, SigWLen, Ssh) of
true ->
{authorized, User,
ssh_transport:ssh_packet(
@@ -518,7 +517,7 @@ pre_verify_sig(User, KeyBlob, Opts) ->
false
end.
-verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, Opts) ->
+verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, #ssh{opts = Opts} = Ssh) ->
try
Alg = binary_to_list(AlgBin),
{KeyCb,KeyCbOpts} = ?GET_OPT(key_cb, Opts),
@@ -529,7 +528,7 @@ verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, Opts) ->
<<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen,
<<?UINT32(AlgLen), _Alg:AlgLen/binary,
?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig,
- ssh_transport:verify(PlainText, ssh_transport:sha(Alg), Sig, Key)
+ ssh_transport:verify(PlainText, ssh_transport:sha(Alg), Sig, Key, Ssh)
catch
_:_ ->
false
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index af9ad52d68..eb2c2848f3 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -146,7 +146,26 @@ msg_formater(msg, {trace_ts,_Pid,return_from,{ssh_message,encode,1},_Res,_TS}, D
msg_formater(msg, {trace_ts,_Pid,call,{ssh_message,decode,_},_TS}, D) ->
D;
msg_formater(msg, {trace_ts,Pid,return_from,{ssh_message,decode,1},Msg,TS}, D) ->
- fmt("~n~s ~p RECV ~s~n", [ts(TS),Pid,wr_record(shrink_bin(Msg))], D);
+ Extra =
+ case Msg of
+ #ssh_msg_userauth_info_request{data = D0} ->
+ try ssh_message:decode_keyboard_interactive_prompts(D0, [])
+ of
+ Acc ->
+ io_lib:format(" -- decoded data:~n", []) ++
+ element(1,
+ lists:mapfoldl(
+ fun({Prompt,Echo}, N) ->
+ {io_lib:format(" prompt[~p]: \"~s\" (echo=~p)~n",[N,Prompt,Echo]), N+1}
+ end, 1, Acc))
+ catch
+ _:_ ->
+ ""
+ end;
+ _ ->
+ ""
+ end,
+ fmt("~n~s ~p RECV ~s~s~n", [ts(TS),Pid,wr_record(shrink_bin(Msg)),Extra], D);
msg_formater(_auth, {trace_ts,Pid,return_from,{ssh_message,decode,1},#ssh_msg_userauth_failure{authentications=As},TS}, D) ->
fmt("~n~s ~p Client login FAILURE. Try ~s~n", [ts(TS),Pid,As], D);
@@ -232,21 +251,22 @@ msg_formater(_, {trace_ts,Pid,return_from, {ssh_transport,known_host_key,3}, Res
end;
msg_formater(_, {trace_ts,Pid,call,{ssh_auth,publickey_msg,[[SigAlg,#ssh{user=User}]]},TS}, D) ->
- fmt("~n~s ~p Client will try to login user ~p with public key algorithm ~p~n", [ts(TS),Pid,User,SigAlg], D);
+ fmt("~n~s ~p Client will try to login user ~p with method: public key algorithm ~p~n", [ts(TS),Pid,User,SigAlg], D);
msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,publickey_msg,1},{not_ok,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p can't login with that kind of public key~n", [ts(TS),Pid,User], D);
-msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,publickey_msg,1},{_,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p logged in~n", [ts(TS),Pid,User], D);
+ fmt("~s ~p User ~p can't use that kind of public key~n", [ts(TS),Pid,User], D);
+msg_formater(_, {trace_ts,_Pid,return_from,{ssh_auth,publickey_msg,1},_,_TS}, D) -> D;
msg_formater(_, {trace_ts,Pid,call,{ssh_auth,password_msg,[[#ssh{user=User}]]},TS}, D) ->
- fmt("~n~s ~p Client will try to login user ~p with password~n", [ts(TS),Pid,User], D);
+ fmt("~n~s ~p Client will try to login user ~p with method: password~n", [ts(TS),Pid,User], D);
msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,password_msg,1},{not_ok,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p can't login with password~n", [ts(TS),Pid,User], D);
+ fmt("~s ~p User ~p can't use method password as login method~n", [ts(TS),Pid,User], D);
+msg_formater(_, {trace_ts,_Pid,return_from,{ssh_auth,password_msg,1},_Result,_TS}, D) -> D;
msg_formater(_, {trace_ts,Pid,call,{ssh_auth,keyboard_interactive_msg,[[#ssh{user=User}]]},TS}, D) ->
- fmt("~n~s ~p Client will try to login user ~p with password~n", [ts(TS),Pid,User], D);
+ fmt("~n~s ~p Client will try to login user ~p with method: keyboard-interactive~n", [ts(TS),Pid,User], D);
msg_formater(_, {trace_ts,Pid,return_from,{ssh_auth,keyboard_interactive_msg,1},{not_ok,#ssh{user=User}},TS}, D) ->
- fmt("~s ~p User ~p can't login with keyboard_interactive password~n", [ts(TS),Pid,User], D);
+ fmt("~s ~p User ~p can't use method keyboard-interactive as login method~n", [ts(TS),Pid,User], D);
+msg_formater(_, {trace_ts,_Pid,return_from,{ssh_auth,keyboard_interactive_msg,1},_Result,_TS}, D) -> D;
msg_formater(msg, {trace_ts,Pid,send,{tcp,Sock,Bytes},Pid,TS}, D) ->
fmt("~n~s ~p TCP SEND on ~p~n ~p~n", [ts(TS),Pid,Sock, shrink_bin(Bytes)], D);
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 90a94a7e86..154894cda8 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -51,7 +51,7 @@
extract_public_key/1,
ssh_packet/2, pack/2,
valid_key_sha_alg/2,
- sha/1, sign/3, verify/4]).
+ sha/1, sign/3, verify/5]).
%%% For test suites
-export([pack/3]).
@@ -825,7 +825,7 @@ extract_public_key(#{engine:=_, key_id:=_, algorithm:=Alg} = M) ->
verify_host_key(#ssh{algorithms=Alg}=SSH, PublicKey, Digest, {AlgStr,Signature}) ->
case atom_to_list(Alg#alg.hkey) of
AlgStr ->
- case verify(Digest, sha(Alg#alg.hkey), Signature, PublicKey) of
+ case verify(Digest, sha(Alg#alg.hkey), Signature, PublicKey, SSH) of
false ->
{error, bad_signature};
true ->
@@ -1288,7 +1288,7 @@ mk_dss_sig(DerSignature) ->
<<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>.
-verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key) ->
+verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key, _) ->
case Sig of
<<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> ->
Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}),
@@ -1296,7 +1296,7 @@ verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key) ->
_ ->
false
end;
-verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key) ->
+verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) ->
case Sig of
<<?UINT32(Rlen),R:Rlen/big-signed-integer-unit:8,
?UINT32(Slen),S:Slen/big-signed-integer-unit:8>> ->
@@ -1306,7 +1306,15 @@ verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key) ->
_ ->
false
end;
-verify(PlainText, HashAlg, Sig, Key) ->
+
+verify(PlainText, HashAlg, Sig, #'RSAPublicKey'{}=Key, #ssh{role = server,
+ c_version = "SSH-2.0-OpenSSH_7."++_})
+ when HashAlg == sha256; HashAlg == sha512 ->
+ %% Public key signing bug in in OpenSSH >= 7.2
+ public_key:verify(PlainText, HashAlg, Sig, Key)
+ orelse public_key:verify(PlainText, sha, Sig, Key);
+
+verify(PlainText, HashAlg, Sig, Key, _) ->
public_key:verify(PlainText, HashAlg, Sig, Key).
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index 98964a2c8a..de6e448ebd 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -29,15 +29,13 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--define(TIMEOUT, 35000).
-
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
suite() ->
[{ct_hooks,[ts_install_cth]},
- {timetrap,{seconds,40}}].
+ {timetrap,{seconds,round(1.5*?TIMEOUT/1000)}}].
all() ->
%% [{group,kex},{group,cipher}... etc
@@ -90,7 +88,7 @@ init_per_suite(Config) ->
" -- Max num algorithms: ~p~n"
,[os:getenv("HOME"),
init:get_argument(home),
- os:cmd("ssh -V"),
+ ssh_test_lib:installed_ssh_version("TIMEOUT"),
ssh:default_algorithms(),
crypto:info_lib(),
ssh_test_lib:default_algorithms(sshc),
@@ -318,10 +316,10 @@ sshc_simple_exec_os_cmd(Config) ->
ok;
false ->
ct:log("Bad result: ~p~nExpected: ~p~nMangled result: ~p", [RawResult,Expect,Lines]),
- {fail, "Bad result"}
+ {fail, "Bad result (see log in testcase)"}
end
after ?TIMEOUT ->
- ct:fail("Did not receive answer")
+ ct:fail("Did not receive answer (timeout)")
end.
%%--------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index 9bbd9da817..ba4518cfe6 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -91,7 +91,7 @@ end_per_suite(Config) ->
init_per_group(openssh, Config) ->
case ssh_test_lib:gen_tcp_connect("localhost", 22, []) of
{error,econnrefused} ->
- {skip,"No openssh deamon"};
+ {skip,"No openssh deamon (econnrefused)"};
{ok, Socket} ->
gen_tcp:close(Socket),
ssh_test_lib:openssh_sanity_check(Config)
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index 7aa3d8a00a..c2f9c0eba8 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -181,8 +181,9 @@ init_per_group(openssh_server, Config) ->
[{peer, {fmt_host(IPx),Portx}}, {group, openssh_server} | Config];
{error,"Key exchange failed"} ->
{skip, "openssh server doesn't support the tested kex algorithm"};
- _ ->
- {skip, "No openssh server"}
+ Other ->
+ ct:log("No openssh server. Cause:~n~p~n",[Other]),
+ {skip, "No openssh daemon (see log in testcase)"}
end;
init_per_group(remote_tar, Config) ->
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 763649a12f..5fc948fbed 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -34,7 +34,7 @@
-define(PASSWD, "Sesame").
-define(XFER_PACKET_SIZE, 32768).
-define(XFER_WINDOW_SIZE, 4*?XFER_PACKET_SIZE).
--define(TIMEOUT, 10000).
+-define(SSH_TIMEOUT, 10000).
-define(REG_ATTERS, <<0,0,0,0,1>>).
-define(UNIX_EPOCH, 62167219200).
@@ -161,9 +161,9 @@ init_per_testcase(TestCase, Config) ->
{silently_accept_hosts, true}]),
{ok, Channel} =
ssh_connection:session_channel(Cm, ?XFER_WINDOW_SIZE,
- ?XFER_PACKET_SIZE, ?TIMEOUT),
+ ?XFER_PACKET_SIZE, ?SSH_TIMEOUT),
- success = ssh_connection:subsystem(Cm, Channel, "sftp", ?TIMEOUT),
+ success = ssh_connection:subsystem(Cm, Channel, "sftp", ?SSH_TIMEOUT),
ProtocolVer = case atom_to_list(TestCase) of
"ver3_" ++ _ ->
diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl
index 83819b97a5..2d7bf75847 100644
--- a/lib/ssh/test/ssh_test_lib.erl
+++ b/lib/ssh/test/ssh_test_lib.erl
@@ -28,9 +28,7 @@
-include_lib("public_key/include/public_key.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("ssh/src/ssh_transport.hrl").
-
-
--define(TIMEOUT, 50000).
+-include("ssh_test_lib.hrl").
%%%----------------------------------------------------------------
connect(Port, Options) when is_integer(Port) ->
@@ -600,6 +598,7 @@ check_ssh_client_support2(P) ->
{P, {data, _A}} ->
check_ssh_client_support2(P);
{P, {exit_status, E}} ->
+ ct:log("~p:~p exit_status:~n~p",[?MODULE,?LINE,E]),
E
after 5000 ->
ct:log("Openssh command timed out ~n"),
@@ -651,14 +650,14 @@ default_algorithms(sshc, DaemonOptions) ->
{hostport,Srvr,{_Host,Port}} ->
spawn(fun()-> os:cmd(lists:concat(["ssh -o \"StrictHostKeyChecking no\" -p ",Port," localhost"])) end)
after ?TIMEOUT ->
- ct:fail("No server respons 1")
+ ct:fail("No server respons (timeout) 1")
end,
receive
{result,Srvr,L} ->
L
after ?TIMEOUT ->
- ct:fail("No server respons 2")
+ ct:fail("No server respons (timeout) 2")
end.
run_fake_ssh({ok,InitialState}) ->
@@ -772,12 +771,12 @@ ssh_type1() ->
not_found;
Path ->
ct:log("~p:~p Found \"ssh\" at ~p",[?MODULE,?LINE,Path]),
- case os:cmd("ssh -V") of
+ case installed_ssh_version(timeout) of
Version = "OpenSSH" ++ _ ->
ct:log("~p:~p Found OpenSSH ~p",[?MODULE,?LINE,Version]),
openSSH;
- Str ->
- ct:log("ssh client ~p is unknown",[Str]),
+ Other ->
+ ct:log("ssh client ~p is unknown",[Other]),
unknown
end
end
@@ -787,6 +786,20 @@ ssh_type1() ->
not_found
end.
+installed_ssh_version(TimeoutReturn) ->
+ Parent = self(),
+ Pid = spawn(fun() ->
+ Parent ! {open_ssh_version, os:cmd("ssh -V")}
+ end),
+ receive
+ {open_ssh_version, V} ->
+ V
+ after ?TIMEOUT ->
+ exit(Pid, kill),
+ TimeoutReturn
+ end.
+
+
algo_intersection([], _) -> [];
diff --git a/lib/ssh/test/ssh_test_lib.hrl b/lib/ssh/test/ssh_test_lib.hrl
index 54c93b7e87..eaf856e6e8 100644
--- a/lib/ssh/test/ssh_test_lib.hrl
+++ b/lib/ssh/test/ssh_test_lib.hrl
@@ -1,4 +1,9 @@
%%-------------------------------------------------------------------------
+%% Timeout time in ms
+%%-------------------------------------------------------------------------
+-define(TIMEOUT, 27000).
+
+%%-------------------------------------------------------------------------
%% Check for usable crypt
%%-------------------------------------------------------------------------
-define(CHECK_CRYPTO(Available),
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index 75d5b5e296..b20764ce47 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -27,7 +27,6 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--define(TIMEOUT, 50000).
-define(SSH_DEFAULT_PORT, 22).
-define(REKEY_DATA_TMO, 65000).
@@ -69,7 +68,7 @@ init_per_suite(Config) ->
?CHECK_CRYPTO(
case gen_tcp:connect("localhost", 22, []) of
{error,econnrefused} ->
- {skip,"No openssh deamon"};
+ {skip,"No openssh deamon (econnrefused)"};
_ ->
ssh_test_lib:openssh_sanity_check(Config)
end
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 59775d2d7f..004db6e3a2 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.6.2
+SSH_VSN = 4.6.4
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 37c916e585..79176f5edf 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,61 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 8.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Packet options cannot be supported for unreliable
+ transports, that is, packet option for DTLS over udp will
+ not be supported.</p>
+ <p>
+ Own Id: OTP-14664</p>
+ </item>
+ <item>
+ <p>
+ Ensure data delivery before close if possible. This fix
+ is related to fix in PR-1479.</p>
+ <p>
+ Own Id: OTP-14794</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The crypto API is extended to use private/public keys
+ stored in an Engine for sign/verify or encrypt/decrypt
+ operations.</p>
+ <p>
+ The ssl application provides an API to use this new
+ engine concept in TLS.</p>
+ <p>
+ Own Id: OTP-14448</p>
+ </item>
+ <item>
+ <p>
+ Implemented renegotiation for DTLS</p>
+ <p>
+ Own Id: OTP-14563</p>
+ </item>
+ <item>
+ <p>
+ A new command line option <c>-ssl_dist_optfile</c> has
+ been added to facilitate specifying the many options
+ needed when using SSL as the distribution protocol.</p>
+ <p>
+ Own Id: OTP-14657</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 8.2.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssl/doc/src/ssl_introduction.xml b/lib/ssl/doc/src/ssl_introduction.xml
index d3e39dbb01..25b05a769d 100644
--- a/lib/ssl/doc/src/ssl_introduction.xml
+++ b/lib/ssl/doc/src/ssl_introduction.xml
@@ -36,7 +36,7 @@
<title>Purpose</title>
<p>Transport Layer Security (TLS) and its predecessor, the Secure
Sockets Layer (SSL), are cryptographic protocols designed to
- provide communications security over a computer network. The protocols use
+ provide communications security over a computer network. The protocols
use X.509 certificates and hence public key (asymmetric) cryptography to
authenticate the counterpart with whom they communicate,
and to exchange a symmetric key for payload encryption. The protocol provides
diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml
index f84cd6e391..61918a346d 100644
--- a/lib/ssl/doc/src/using_ssl.xml
+++ b/lib/ssl/doc/src/using_ssl.xml
@@ -152,4 +152,41 @@ Shell got {ssl,{sslsocket,[...]},"foo"}
ok</code>
</section>
</section>
+
+ <section>
+ <title>Using an Engine Stored Key</title>
+
+ <p>Erlang ssl application is able to use private keys provided
+ by OpenSSL engines using the following mechanism:</p>
+
+ <code type="erl">1> ssl:start().
+ok</code>
+
+ <p>Load a crypto engine, should be done once per engine used. For example
+ dynamically load the engine called <c>MyEngine</c>:
+ </p>
+ <code type="erl">2> {ok, EngineRef} =
+crypto:engine_load(&lt;&lt;"dynamic">>,
+ [{&lt;&lt;"SO_PATH">>, "/tmp/user/engines/MyEngine"},&lt;&lt;"LOAD">>],[]).
+{ok,#Ref&lt;0.2399045421.3028942852.173962>}
+ </code>
+
+ <p>Create a map with the engine information and the algorithm used by the engine:</p>
+ <code type="erl">3> PrivKey =
+ #{algorithm => rsa,
+ engine => EngineRef,
+ key_id => "id of the private key in Engine"}.
+ </code>
+ <p>Use the map in the ssl key option:</p>
+ <code type="erl">4> {ok, SSLSocket} =
+ssl:connect("localhost", 9999,
+ [{cacertfile, "cacerts.pem"},
+ {certfile, "cert.pem"},
+ {key, PrivKey}], infinity).
+ </code>
+
+ <p>See also <seealso marker="crypto:engine_load#engine_load"> crypto documentation</seealso> </p>
+
+ </section>
+
</chapter>
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index e5760e7951..3b5a548f72 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -143,10 +143,16 @@ next_record(#state{role = server,
dtls_udp_listener:active_once(Listener, Client, self()),
{no_record, State};
next_record(#state{role = client,
- socket = {_Server, Socket},
+ socket = {_Server, Socket} = DTLSSocket,
+ close_tag = CloseTag,
transport_cb = Transport} = State) ->
- dtls_socket:setopts(Transport, Socket, [{active,once}]),
- {no_record, State};
+ case dtls_socket:setopts(Transport, Socket, [{active,once}]) of
+ ok ->
+ {no_record, State};
+ _ ->
+ self() ! {CloseTag, DTLSSocket},
+ {no_record, State}
+ end;
next_record(State) ->
{no_record, State}.
@@ -218,12 +224,12 @@ next_event(StateName, Record,
#state{connection_states = #{current_read := #{epoch := CurrentEpoch}}} = State0, Actions) ->
case Record of
no_record ->
- {next_state, StateName, State0, Actions};
+ {next_state, StateName, State0, Actions};
#ssl_tls{epoch = CurrentEpoch,
version = Version} = Record ->
State = dtls_version(StateName, Version, State0),
- {next_state, StateName, State,
- [{next_event, internal, {protocol_record, Record}} | Actions]};
+ {next_state, StateName, State,
+ [{next_event, internal, {protocol_record, Record}} | Actions]};
#ssl_tls{epoch = _Epoch,
version = _Version} = _Record ->
%% TODO maybe buffer later epoch
@@ -605,6 +611,12 @@ certify(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
certify(internal = Type, #server_hello_done{} = Event, State) ->
ssl_connection:certify(Type, Event, prepare_flight(State), ?MODULE);
+certify(internal, #change_cipher_spec{type = <<1>>}, State0) ->
+ {State1, Actions0} = send_handshake_flight(State0, retransmit_epoch(?FUNCTION_NAME, State0)),
+ {Record, State2} = next_record(State1),
+ {next_state, ?FUNCTION_NAME, State, Actions} = next_event(?FUNCTION_NAME, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions};
certify(state_timeout, Event, State) ->
handle_state_timeout(Event, ?FUNCTION_NAME, State);
certify(Type, Event, State) ->
@@ -864,12 +876,14 @@ handle_info(new_cookie_secret, StateName,
handle_info(Msg, StateName, State) ->
ssl_connection:StateName(info, Msg, State, ?MODULE).
-handle_state_timeout(flight_retransmission_timeout, StateName,
- #state{flight_state = {retransmit, NextTimeout}} = State0) ->
- {State1, Actions} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
+handle_state_timeout(flight_retransmission_timeout, StateName,
+ #state{flight_state = {retransmit, NextTimeout}} = State0) ->
+ {State1, Actions0} = send_handshake_flight(State0#state{flight_state = {retransmit, NextTimeout}},
retransmit_epoch(StateName, State0)),
- {Record, State} = next_record(State1),
- next_event(StateName, Record, State, Actions).
+ {Record, State2} = next_record(State1),
+ {next_state, StateName, State, Actions} = next_event(StateName, Record, State2, Actions0),
+ %% This will reset the retransmission timer by repeating the enter state event
+ {repeat_state, State, Actions}.
handle_alerts([], Result) ->
Result;
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 5e8f5c2ca0..6071eece13 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -67,7 +67,8 @@ client_hello(Host, Port, ConnectionStates, SslOpts,
%%--------------------------------------------------------------------
client_hello(Host, Port, Cookie, ConnectionStates,
#ssl_options{versions = Versions,
- ciphers = UserSuites
+ ciphers = UserSuites,
+ fallback = Fallback
} = SslOpts,
Cache, CacheCb, Renegotiation, OwnCert) ->
Version = dtls_record:highest_protocol_version(Versions),
@@ -83,7 +84,9 @@ client_hello(Host, Port, Cookie, ConnectionStates,
#client_hello{session_id = Id,
client_version = Version,
- cipher_suites = ssl_handshake:cipher_suites(CipherSuites, Renegotiation),
+ cipher_suites =
+ ssl_handshake:cipher_suites(CipherSuites,
+ Renegotiation, Fallback),
compression_methods = ssl_record:compressions(),
random = SecParams#security_parameters.client_random,
cookie = Cookie,
diff --git a/lib/ssl/src/dtls_udp_listener.erl b/lib/ssl/src/dtls_udp_listener.erl
index c9e04767aa..0608c6bd2b 100644
--- a/lib/ssl/src/dtls_udp_listener.erl
+++ b/lib/ssl/src/dtls_udp_listener.erl
@@ -84,7 +84,7 @@ init([Port, EmOpts, InetOptions, DTLSOptions]) ->
listener = Socket,
close = false}}
catch _:_ ->
- {error, closed}
+ {stop, {shutdown, {error, closed}}}
end.
handle_call({accept, _}, _, #state{close = true} = State) ->
{reply, {error, closed}, State};
@@ -153,15 +153,18 @@ handle_info({udp_error, Socket, Error}, #state{listener = Socket} = State) ->
handle_info({'DOWN', _, process, Pid, _}, #state{clients = Clients,
dtls_processes = Processes0,
+ dtls_msq_queues = MsgQueues0,
close = ListenClosed} = State) ->
Client = kv_get(Pid, Processes0),
Processes = kv_delete(Pid, Processes0),
+ MsgQueues = kv_delete(Client, MsgQueues0),
case ListenClosed andalso kv_empty(Processes) of
true ->
{stop, normal, State};
false ->
{noreply, State#state{clients = set_delete(Client, Clients),
- dtls_processes = Processes}}
+ dtls_processes = Processes,
+ dtls_msq_queues = MsgQueues}}
end.
terminate(_Reason, _State) ->
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index c5b55641a1..3c6cd254c1 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -63,4 +63,4 @@
{env, []},
{mod, {ssl_app, []}},
{runtime_dependencies, ["stdlib-3.2","public_key-1.5","kernel-6.0",
- "erts-10.0","crypto-3.3", "inets-5.10.7"]}]}.
+ "erts-10.0","crypto-4.2", "inets-5.10.7"]}]}.
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 61d61b53dd..0c55af9174 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -67,7 +67,7 @@
%% Cipher suites handling
-export([available_suites/2, available_signature_algs/2, available_signature_algs/4,
- cipher_suites/2, prf/6, select_session/11, supported_ecc/1,
+ cipher_suites/3, prf/6, select_session/11, supported_ecc/1,
premaster_secret/2, premaster_secret/3, premaster_secret/4]).
%% Extensions handling
@@ -801,6 +801,11 @@ available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, Su
available_signature_algs(_, _, _, _) ->
undefined.
+cipher_suites(Suites, Renegotiation, true) ->
+ %% TLS_FALLBACK_SCSV should be placed last -RFC7507
+ cipher_suites(Suites, Renegotiation) ++ [?TLS_FALLBACK_SCSV];
+cipher_suites(Suites, Renegotiation, false) ->
+ cipher_suites(Suites, Renegotiation).
cipher_suites(Suites, false) ->
[?TLS_EMPTY_RENEGOTIATION_INFO_SCSV | Suites];
cipher_suites(Suites, true) ->
@@ -1060,7 +1065,6 @@ select_hashsign(HashSigns, Cert, KeyExAlgo,
select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version);
select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns,
{Major, Minor}) when Major >= 3 andalso Minor >= 3 ->
- #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp),
#'OTPCertificate'{tbsCertificate = TBSCert,
signatureAlgorithm = {_,SignAlgo, _}} = public_key:pkix_decode_cert(Cert, otp),
#'OTPSubjectPublicKeyInfo'{algorithm = {_, SubjAlgo, _}} =
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 406a095d2e..cf2f3a2b62 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -439,8 +439,13 @@ init(Type, Event, State) ->
error({call, From}, {start, _Timeout}, {Error, State}) ->
ssl_connection:stop_and_reply(
normal, {reply, From, {error, Error}}, State);
-error({call, _} = Call, Msg, State) ->
- gen_handshake(?FUNCTION_NAME, Call, Msg, State);
+error({call, From}, {start, _Timeout},
+ #state{protocol_specific = #{error := Error}} = State) ->
+ ssl_connection:stop_and_reply(
+ normal, {reply, From, {error, Error}}, State);
+error({call, _} = Call, Msg, {Error, #state{protocol_specific = Map} = State}) ->
+ gen_handshake(?FUNCTION_NAME, Call, Msg,
+ State#state{protocol_specific = Map#{error => Error}});
error(_, _, _) ->
{keep_state_and_data, [postpone]}.
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index d59e817ffb..8817418fb0 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -67,14 +67,7 @@ client_hello(Host, Port, ConnectionStates,
AvailableCipherSuites,
SslOpts, ConnectionStates,
Renegotiation),
- CipherSuites =
- case Fallback of
- true ->
- [?TLS_FALLBACK_SCSV |
- ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation)];
- false ->
- ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation)
- end,
+ CipherSuites = ssl_handshake:cipher_suites(AvailableCipherSuites, Renegotiation, Fallback),
Id = ssl_session:client_id({Host, Port, SslOpts}, Cache, CacheCb, OwnCert),
#client_hello{session_id = Id,
client_version = Version,
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 17b66aef40..cb54168d36 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -1,8 +1,4 @@
{suites,"../ssl_test",all}.
-{skip_cases, "../ssl_test",
- ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple,
- use_pem_cache, bypass_pem_cache],
- "Benchmarks run separately"}.
{skip_suites, "../ssl_test",
- [ssl_dist_bench_SUITE],
+ [ssl_bench_SUITE, ssl_dist_bench_SUITE],
"Benchmarks run separately"}.
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index cf6481d14c..2650399eea 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1 @@
-SSL_VSN = 8.2.2
+SSL_VSN = 8.2.3
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml
index 5332d7aba5..db96beed6c 100644
--- a/lib/stdlib/doc/src/digraph.xml
+++ b/lib/stdlib/doc/src/digraph.xml
@@ -170,6 +170,10 @@
<p>If the edge would create a cycle in
an <seealso marker="#acyclic_digraph">acyclic digraph</seealso>,
<c>{error,&nbsp;{bad_edge,&nbsp;<anno>Path</anno>}}</c> is returned.
+ If <c><anno>G</anno></c> already has an edge with value
+ <c><anno>E</anno></c> connecting a different pair of vertices,
+ <c>{error,&nbsp;{bad_edge,&nbsp;[<anno>V1</anno>,&nbsp;<anno>V2</anno>]}}</c>
+ is returned.
If either of <c><anno>V1</anno></c> or <c><anno>V2</anno></c> is not
a vertex of digraph <c><anno>G</anno></c>,
<c>{error,&nbsp;{bad_vertex,&nbsp;</c><anno>V</anno><c>}}</c> is
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index d396f1de8f..b61e5b9b9e 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -31,6 +31,49 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 3.4.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Make <c>ets:i/1</c> exit cleaner when ^D is input
+ while browsing a table. Only the old Erlang shell is
+ affected (<c>erl(1)</c> flag <c>-oldshell</c>). </p>
+ <p>
+ Own Id: OTP-14663</p>
+ </item>
+ <item>
+ <p>
+ Fixed handling of windows UNC paths in module
+ <c>filename</c>.</p>
+ <p>
+ Own Id: OTP-14693</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Improve performance of the new string functionality when
+ handling ASCII characters.</p>
+ <p>
+ Own Id: OTP-14670</p>
+ </item>
+ <item>
+ <p>
+ Added a clarification to the documentation of
+ <c>unicode:characters_to_list/2</c>.</p>
+ <p>
+ Own Id: OTP-14798</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.4.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index c8cf6fdffe..6ea4147abf 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -24,22 +24,11 @@
-export([encode/1, decode/1, mime_decode/1,
encode_to_string/1, decode_to_string/1, mime_decode_to_string/1]).
-%%-------------------------------------------------------------------------
%% The following type is a subtype of string() for return values
%% of (some) functions of this module.
-%%-------------------------------------------------------------------------
-
-type ascii_string() :: [1..255].
-type ascii_binary() :: binary().
-%%-------------------------------------------------------------------------
-%% encode_to_string(ASCII) -> Base64String
-%% ASCII - string() | binary()
-%% Base64String - string()
-%%
-%% Description: Encodes a plain ASCII string (or binary) into base64.
-%%-------------------------------------------------------------------------
-
-spec encode_to_string(Data) -> Base64String when
Data :: ascii_string() | ascii_binary(),
Base64String :: ascii_string().
@@ -47,66 +36,67 @@
encode_to_string(Bin) when is_binary(Bin) ->
encode_to_string(binary_to_list(Bin));
encode_to_string(List) when is_list(List) ->
- encode_l(List).
-
-%%-------------------------------------------------------------------------
-%% encode(ASCII) -> Base64
-%% ASCII - string() | binary()
-%% Base64 - binary()
-%%
-%% Description: Encodes a plain ASCII string (or binary) into base64.
-%%-------------------------------------------------------------------------
+ encode_list_to_string(List).
-spec encode(Data) -> Base64 when
Data :: ascii_string() | ascii_binary(),
Base64 :: ascii_binary().
encode(Bin) when is_binary(Bin) ->
- encode_binary(Bin);
+ encode_binary(Bin, <<>>);
encode(List) when is_list(List) ->
- list_to_binary(encode_l(List)).
-
--spec encode_l(ascii_string()) -> ascii_string().
+ encode_list(List, <<>>).
-encode_l([]) ->
+encode_list_to_string([]) ->
[];
-encode_l([A]) ->
- [b64e(A bsr 2),
- b64e((A band 3) bsl 4), $=, $=];
-encode_l([A,B]) ->
- [b64e(A bsr 2),
- b64e(((A band 3) bsl 4) bor (B bsr 4)),
- b64e((B band 15) bsl 2), $=];
-encode_l([A,B,C|Ls]) ->
- BB = (A bsl 16) bor (B bsl 8) bor C,
+encode_list_to_string([B1]) ->
+ [b64e(B1 bsr 2),
+ b64e((B1 band 3) bsl 4), $=, $=];
+encode_list_to_string([B1,B2]) ->
+ [b64e(B1 bsr 2),
+ b64e(((B1 band 3) bsl 4) bor (B2 bsr 4)),
+ b64e((B2 band 15) bsl 2), $=];
+encode_list_to_string([B1,B2,B3|Ls]) ->
+ BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
[b64e(BB bsr 18),
b64e((BB bsr 12) band 63),
b64e((BB bsr 6) band 63),
- b64e(BB band 63) | encode_l(Ls)].
-
-encode_binary(Bin) ->
- Split = 3*(byte_size(Bin) div 3),
- <<Main0:Split/binary,Rest/binary>> = Bin,
- Main = << <<(b64e(C)):8>> || <<C:6>> <= Main0 >>,
- case Rest of
- <<A:6,B:6,C:4>> ->
- <<Main/binary,(b64e(A)):8,(b64e(B)):8,(b64e(C bsl 2)):8,$=:8>>;
- <<A:6,B:2>> ->
- <<Main/binary,(b64e(A)):8,(b64e(B bsl 4)):8,$=:8,$=:8>>;
- <<>> ->
- Main
- end.
+ b64e(BB band 63) | encode_list_to_string(Ls)].
-%%-------------------------------------------------------------------------
-%% mime_decode(Base64) -> ASCII
-%% decode(Base64) -> ASCII
-%% Base64 - string() | binary()
-%% ASCII - binary()
-%%
-%% Description: Decodes an base64 encoded string to plain ASCII.
-%% mime_decode strips away all characters not Base64 before converting,
-%% whereas decode crashes if an illegal character is found
-%%-------------------------------------------------------------------------
+encode_binary(<<>>, A) ->
+ A;
+encode_binary(<<B1:8>>, A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,(b64e((B1 band 3) bsl 4)):8,$=:8,$=:8>>;
+encode_binary(<<B1:8, B2:8>>, A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,
+ (b64e(((B1 band 3) bsl 4) bor (B2 bsr 4))):8,
+ (b64e((B2 band 15) bsl 2)):8, $=:8>>;
+encode_binary(<<B1:8, B2:8, B3:8, Ls/bits>>, A) ->
+ BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
+ encode_binary(Ls,
+ <<A/bits,(b64e(BB bsr 18)):8,
+ (b64e((BB bsr 12) band 63)):8,
+ (b64e((BB bsr 6) band 63)):8,
+ (b64e(BB band 63)):8>>).
+
+encode_list([], A) ->
+ A;
+encode_list([B1], A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,(b64e((B1 band 3) bsl 4)):8,$=:8,$=:8>>;
+encode_list([B1,B2], A) ->
+ <<A/bits,(b64e(B1 bsr 2)):8,
+ (b64e(((B1 band 3) bsl 4) bor (B2 bsr 4))):8,
+ (b64e((B2 band 15) bsl 2)):8, $=:8>>;
+encode_list([B1,B2,B3|Ls], A) ->
+ BB = (B1 bsl 16) bor (B2 bsl 8) bor B3,
+ encode_list(Ls,
+ <<A/bits,(b64e(BB bsr 18)):8,
+ (b64e((BB bsr 12) band 63)):8,
+ (b64e((BB bsr 6) band 63)):8,
+ (b64e(BB band 63)):8>>).
+
+%% mime_decode strips away all characters not Base64 before
+%% converting, whereas decode crashes if an illegal character is found
-spec decode(Base64) -> Data when
Base64 :: ascii_string() | ascii_binary(),
@@ -122,32 +112,13 @@ decode(List) when is_list(List) ->
Data :: ascii_binary().
mime_decode(Bin) when is_binary(Bin) ->
- mime_decode_binary(<<>>, Bin);
+ mime_decode_binary(Bin, <<>>);
mime_decode(List) when is_list(List) ->
- mime_decode(list_to_binary(List)).
+ mime_decode_list(List, <<>>).
--spec decode_l(ascii_string()) -> ascii_string().
-
-decode_l(List) ->
- L = strip_spaces(List, []),
- decode(L, []).
-
--spec mime_decode_l(ascii_string()) -> ascii_string().
-
-mime_decode_l(List) ->
- L = strip_illegal(List, [], 0),
- decode(L, []).
-
-%%-------------------------------------------------------------------------
-%% mime_decode_to_string(Base64) -> ASCII
-%% decode_to_string(Base64) -> ASCII
-%% Base64 - string() | binary()
-%% ASCII - binary()
-%%
-%% Description: Decodes an base64 encoded string to plain ASCII.
-%% mime_decode strips away all characters not Base64 before converting,
-%% whereas decode crashes if an illegal character is found
-%%-------------------------------------------------------------------------
+%% mime_decode_to_string strips away all characters not Base64 before
+%% converting, whereas decode_to_string crashes if an illegal
+%% character is found
-spec decode_to_string(Base64) -> DataString when
Base64 :: ascii_string() | ascii_binary(),
@@ -156,7 +127,7 @@ mime_decode_l(List) ->
decode_to_string(Bin) when is_binary(Bin) ->
decode_to_string(binary_to_list(Bin));
decode_to_string(List) when is_list(List) ->
- decode_l(List).
+ decode_list_to_string(List).
-spec mime_decode_to_string(Base64) -> DataString when
Base64 :: ascii_string() | ascii_binary(),
@@ -165,115 +136,195 @@ decode_to_string(List) when is_list(List) ->
mime_decode_to_string(Bin) when is_binary(Bin) ->
mime_decode_to_string(binary_to_list(Bin));
mime_decode_to_string(List) when is_list(List) ->
- mime_decode_l(List).
-
-%% One-based decode map.
--define(DECODE_MAP,
- {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, %1-15
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, %16-31
- ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad,bad,63, %32-47
- 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,eq,bad,bad, %48-63
- bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
- 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,bad,
- bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
- 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
- bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad}).
+ mime_decode_list_to_string(List).
-decode_binary(<<C1:8, Cs/bits>>, A) ->
- case element(C1, ?DECODE_MAP) of
- ws -> decode_binary(Cs, A);
- B1 -> decode_binary(Cs, A, B1)
+%% Skipping pad character if not at end of string. Also liberal about
+%% excess padding and skipping of other illegal (non-base64 alphabet)
+%% characters. See section 3.3 of RFC4648
+mime_decode_list([0 | Cs], A) ->
+ mime_decode_list(Cs, A);
+mime_decode_list([C1 | Cs], A) ->
+ case b64d(C1) of
+ B1 when is_integer(B1) -> mime_decode_list(Cs, A, B1);
+ _ -> mime_decode_list(Cs, A) % eq is padding
end;
-decode_binary(<<>>, A) ->
+mime_decode_list([], A) ->
A.
-decode_binary(<<C2:8, Cs/bits>>, A, B1) ->
- case element(C2, ?DECODE_MAP) of
- ws -> decode_binary(Cs, A, B1);
- B2 -> decode_binary(Cs, A, B1, B2)
+mime_decode_list([0 | Cs], A, B1) ->
+ mime_decode_list(Cs, A, B1);
+mime_decode_list([C2 | Cs], A, B1) ->
+ case b64d(C2) of
+ B2 when is_integer(B2) ->
+ mime_decode_list(Cs, A, B1, B2);
+ _ -> mime_decode_list(Cs, A, B1) % eq is padding
end.
-decode_binary(<<C3:8, Cs/bits>>, A, B1, B2) ->
- case element(C3, ?DECODE_MAP) of
- ws -> decode_binary(Cs, A, B1, B2);
- B3 -> decode_binary(Cs, A, B1, B2, B3)
+mime_decode_list([0 | Cs], A, B1, B2) ->
+ mime_decode_list(Cs, A, B1, B2);
+mime_decode_list([C3 | Cs], A, B1, B2) ->
+ case b64d(C3) of
+ B3 when is_integer(B3) ->
+ mime_decode_list(Cs, A, B1, B2, B3);
+ eq=B3 ->
+ mime_decode_list_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_list(Cs, A, B1, B2)
end.
-decode_binary(<<C4:8, Cs/bits>>, A, B1, B2, B3) ->
- case element(C4, ?DECODE_MAP) of
- ws -> decode_binary(Cs, A, B1, B2, B3);
- eq when B3 =:= eq -> only_ws_binary(Cs, <<A/binary,B1:6,(B2 bsr 4):2>>);
- eq -> only_ws_binary(Cs, <<A/binary,B1:6,B2:6,(B3 bsr 2):4>>);
- B4 -> decode_binary(Cs, <<A/binary,B1:6,B2:6,B3:6,B4:6>>)
+mime_decode_list([0 | Cs], A, B1, B2, B3) ->
+ mime_decode_list(Cs, A, B1, B2, B3);
+mime_decode_list([C4 | Cs], A, B1, B2, B3) ->
+ case b64d(C4) of
+ B4 when is_integer(B4) ->
+ mime_decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>);
+ eq ->
+ mime_decode_list_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_list(Cs, A, B1, B2, B3)
end.
-only_ws_binary(<<>>, A) ->
- A;
-only_ws_binary(<<C:8, Cs/bits>>, A) ->
- case element(C, ?DECODE_MAP) of
- ws -> only_ws_binary(Cs, A);
- _ -> erlang:error(function_clause)
+mime_decode_list_after_eq([0 | Cs], A, B1, B2, B3) ->
+ mime_decode_list_after_eq(Cs, A, B1, B2, B3);
+mime_decode_list_after_eq([C | Cs], A, B1, B2, B3) ->
+ case b64d(C) of
+ B when is_integer(B) ->
+ %% More valid data, skip the eq as invalid
+ case B3 of
+ eq -> mime_decode_list(Cs, A, B1, B2, B);
+ _ -> mime_decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B:6>>)
+ end;
+ _ -> mime_decode_list_after_eq(Cs, A, B1, B2, B3)
+ end;
+mime_decode_list_after_eq([], A, B1, B2, eq) ->
+ <<A/bits,B1:6,(B2 bsr 4):2>>;
+mime_decode_list_after_eq([], A, B1, B2, B3) ->
+ <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A) ->
+ mime_decode_binary(Cs, A);
+mime_decode_binary(<<C1:8, Cs/bits>>, A) ->
+ case b64d(C1) of
+ B1 when is_integer(B1) -> mime_decode_binary(Cs, A, B1);
+ _ -> mime_decode_binary(Cs, A) % eq is padding
+ end;
+mime_decode_binary(<<>>, A) ->
+ A.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A, B1) ->
+ mime_decode_binary(Cs, A, B1);
+mime_decode_binary(<<C2:8, Cs/bits>>, A, B1) ->
+ case b64d(C2) of
+ B2 when is_integer(B2) ->
+ mime_decode_binary(Cs, A, B1, B2);
+ _ -> mime_decode_binary(Cs, A, B1) % eq is padding
end.
-%% Skipping pad character if not at end of string. Also liberal about
-%% excess padding and skipping of other illegal (non-base64 alphabet)
-%% characters. See section 3.3 of RFC4648
-mime_decode_binary(Result, <<0:8,T/bits>>) ->
- mime_decode_binary(Result, T);
-mime_decode_binary(Result0, <<C:8,T/bits>>) ->
- case element(C, ?DECODE_MAP) of
- Bits when is_integer(Bits) ->
- mime_decode_binary(<<Result0/bits,Bits:6>>, T);
+mime_decode_binary(<<0:8, Cs/bits>>, A, B1, B2) ->
+ mime_decode_binary(Cs, A, B1, B2);
+mime_decode_binary(<<C3:8, Cs/bits>>, A, B1, B2) ->
+ case b64d(C3) of
+ B3 when is_integer(B3) ->
+ mime_decode_binary(Cs, A, B1, B2, B3);
+ eq=B3 ->
+ mime_decode_binary_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_binary(Cs, A, B1, B2)
+ end.
+
+mime_decode_binary(<<0:8, Cs/bits>>, A, B1, B2, B3) ->
+ mime_decode_binary(Cs, A, B1, B2, B3);
+mime_decode_binary(<<C4:8, Cs/bits>>, A, B1, B2, B3) ->
+ case b64d(C4) of
+ B4 when is_integer(B4) ->
+ mime_decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>);
eq ->
- mime_decode_binary_after_eq(Result0, T, false);
- _ ->
- mime_decode_binary(Result0, T)
+ mime_decode_binary_after_eq(Cs, A, B1, B2, B3);
+ _ -> mime_decode_binary(Cs, A, B1, B2, B3)
+ end.
+
+mime_decode_binary_after_eq(<<0:8, Cs/bits>>, A, B1, B2, B3) ->
+ mime_decode_binary_after_eq(Cs, A, B1, B2, B3);
+mime_decode_binary_after_eq(<<C:8, Cs/bits>>, A, B1, B2, B3) ->
+ case b64d(C) of
+ B when is_integer(B) ->
+ %% More valid data, skip the eq as invalid
+ case B3 of
+ eq -> mime_decode_binary(Cs, A, B1, B2, B);
+ _ -> mime_decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B:6>>)
+ end;
+ _ -> mime_decode_binary_after_eq(Cs, A, B1, B2, B3)
end;
-mime_decode_binary(Result, _) ->
- true = is_binary(Result),
- Result.
-
-mime_decode_binary_after_eq(Result, <<0:8,T/bits>>, Eq) ->
- mime_decode_binary_after_eq(Result, T, Eq);
-mime_decode_binary_after_eq(Result0, <<C:8,T/bits>>, Eq) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- mime_decode_binary_after_eq(Result0, T, Eq);
- ws ->
- mime_decode_binary_after_eq(Result0, T, Eq);
+mime_decode_binary_after_eq(<<>>, A, B1, B2, eq) ->
+ <<A/bits,B1:6,(B2 bsr 4):2>>;
+mime_decode_binary_after_eq(<<>>, A, B1, B2, B3) ->
+ <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>.
+
+mime_decode_list_to_string([0 | Cs]) ->
+ mime_decode_list_to_string(Cs);
+mime_decode_list_to_string([C1 | Cs]) ->
+ case b64d(C1) of
+ B1 when is_integer(B1) -> mime_decode_list_to_string(Cs, B1);
+ _ -> mime_decode_list_to_string(Cs) % eq is padding
+ end;
+mime_decode_list_to_string([]) ->
+ [].
+
+mime_decode_list_to_string([0 | Cs], B1) ->
+ mime_decode_list_to_string(Cs, B1);
+mime_decode_list_to_string([C2 | Cs], B1) ->
+ case b64d(C2) of
+ B2 when is_integer(B2) ->
+ mime_decode_list_to_string(Cs, B1, B2);
+ _ -> mime_decode_list_to_string(Cs, B1) % eq is padding
+ end.
+
+mime_decode_list_to_string([0 | Cs], B1, B2) ->
+ mime_decode_list_to_string(Cs, B1, B2);
+mime_decode_list_to_string([C3 | Cs], B1, B2) ->
+ case b64d(C3) of
+ B3 when is_integer(B3) ->
+ mime_decode_list_to_string(Cs, B1, B2, B3);
+ eq=B3 -> mime_decode_list_to_string_after_eq(Cs, B1, B2, B3);
+ _ -> mime_decode_list_to_string(Cs, B1, B2)
+ end.
+
+mime_decode_list_to_string([0 | Cs], B1, B2, B3) ->
+ mime_decode_list_to_string(Cs, B1, B2, B3);
+mime_decode_list_to_string([C4 | Cs], B1, B2, B3) ->
+ case b64d(C4) of
+ B4 when is_integer(B4) ->
+ Bits4x6 = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B4,
+ Octet1 = Bits4x6 bsr 16,
+ Octet2 = (Bits4x6 bsr 8) band 16#ff,
+ Octet3 = Bits4x6 band 16#ff,
+ [Octet1, Octet2, Octet3 | mime_decode_list_to_string(Cs)];
eq ->
- mime_decode_binary_after_eq(Result0, T, true);
- Bits when is_integer(Bits) ->
+ mime_decode_list_to_string_after_eq(Cs, B1, B2, B3);
+ _ -> mime_decode_list_to_string(Cs, B1, B2, B3)
+ end.
+
+mime_decode_list_to_string_after_eq([0 | Cs], B1, B2, B3) ->
+ mime_decode_list_to_string_after_eq(Cs, B1, B2, B3);
+mime_decode_list_to_string_after_eq([C | Cs], B1, B2, B3) ->
+ case b64d(C) of
+ B when is_integer(B) ->
%% More valid data, skip the eq as invalid
- mime_decode_binary(<<Result0/bits,Bits:6>>, T)
+ case B3 of
+ eq -> mime_decode_list_to_string(Cs, B1, B2, B);
+ _ ->
+ Bits4x6 = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B,
+ Octet1 = Bits4x6 bsr 16,
+ Octet2 = (Bits4x6 bsr 8) band 16#ff,
+ Octet3 = Bits4x6 band 16#ff,
+ [Octet1, Octet2, Octet3 | mime_decode_list_to_string(Cs)]
+ end;
+ _ -> mime_decode_list_to_string_after_eq(Cs, B1, B2, B3)
end;
-mime_decode_binary_after_eq(Result0, <<>>, Eq) ->
- %% No more valid data.
- case bit_size(Result0) rem 8 of
- 0 ->
- %% '====' is not uncommon.
- Result0;
- 4 when Eq ->
- %% enforce at least one more '=' only ignoring illegals and spacing
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:4>> = Result0,
- Result;
- 2 ->
- %% remove 2 bits
- Split = byte_size(Result0) - 1,
- <<Result:Split/bytes,_:2>> = Result0,
- Result
- end.
+mime_decode_list_to_string_after_eq([], B1, B2, eq) ->
+ binary_to_list(<<B1:6,(B2 bsr 4):2>>);
+mime_decode_list_to_string_after_eq([], B1, B2, B3) ->
+ binary_to_list(<<B1:6,B2:6,(B3 bsr 2):4>>).
decode_list([C1 | Cs], A) ->
- case element(C1, ?DECODE_MAP) of
+ case b64d(C1) of
ws -> decode_list(Cs, A);
B1 -> decode_list(Cs, A, B1)
end;
@@ -281,122 +332,130 @@ decode_list([], A) ->
A.
decode_list([C2 | Cs], A, B1) ->
- case element(C2, ?DECODE_MAP) of
+ case b64d(C2) of
ws -> decode_list(Cs, A, B1);
B2 -> decode_list(Cs, A, B1, B2)
end.
decode_list([C3 | Cs], A, B1, B2) ->
- case element(C3, ?DECODE_MAP) of
+ case b64d(C3) of
ws -> decode_list(Cs, A, B1, B2);
B3 -> decode_list(Cs, A, B1, B2, B3)
end.
decode_list([C4 | Cs], A, B1, B2, B3) ->
- case element(C4, ?DECODE_MAP) of
+ case b64d(C4) of
ws -> decode_list(Cs, A, B1, B2, B3);
- eq when B3 =:= eq -> only_ws(Cs, <<A/binary,B1:6,(B2 bsr 4):2>>);
- eq -> only_ws(Cs, <<A/binary,B1:6,B2:6,(B3 bsr 2):4>>);
- B4 -> decode_list(Cs, <<A/binary,B1:6,B2:6,B3:6,B4:6>>)
+ eq when B3 =:= eq -> only_ws(Cs, <<A/bits,B1:6,(B2 bsr 4):2>>);
+ eq -> only_ws(Cs, <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>);
+ B4 -> decode_list(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>)
end.
-only_ws([], A) ->
- A;
-only_ws([C | Cs], A) ->
- case element(C, ?DECODE_MAP) of
- ws -> only_ws(Cs, A);
- _ -> erlang:error(function_clause)
- end.
+decode_binary(<<C1:8, Cs/bits>>, A) ->
+ case b64d(C1) of
+ ws -> decode_binary(Cs, A);
+ B1 -> decode_binary(Cs, A, B1)
+ end;
+decode_binary(<<>>, A) ->
+ A.
-decode([], A) -> A;
-decode([$=,$=,C2,C1|Cs], A) ->
- Bits2x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12),
- Octet1 = Bits2x6 bsr 16,
- decode(Cs, [Octet1|A]);
-decode([$=,C3,C2,C1|Cs], A) ->
- Bits3x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12)
- bor (b64d(C3) bsl 6),
- Octet1 = Bits3x6 bsr 16,
- Octet2 = (Bits3x6 bsr 8) band 16#ff,
- decode(Cs, [Octet1,Octet2|A]);
-decode([C4,C3,C2,C1| Cs], A) ->
- Bits4x6 = (b64d(C1) bsl 18) bor (b64d(C2) bsl 12)
- bor (b64d(C3) bsl 6) bor b64d(C4),
- Octet1 = Bits4x6 bsr 16,
- Octet2 = (Bits4x6 bsr 8) band 16#ff,
- Octet3 = Bits4x6 band 16#ff,
- decode(Cs, [Octet1,Octet2,Octet3|A]).
+decode_binary(<<C2:8, Cs/bits>>, A, B1) ->
+ case b64d(C2) of
+ ws -> decode_binary(Cs, A, B1);
+ B2 -> decode_binary(Cs, A, B1, B2)
+ end.
-%%%========================================================================
-%%% Internal functions
-%%%========================================================================
+decode_binary(<<C3:8, Cs/bits>>, A, B1, B2) ->
+ case b64d(C3) of
+ ws -> decode_binary(Cs, A, B1, B2);
+ B3 -> decode_binary(Cs, A, B1, B2, B3)
+ end.
-strip_spaces([], A) -> A;
-strip_spaces([$\s|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([$\t|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([$\r|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([$\n|Cs], A) -> strip_spaces(Cs, A);
-strip_spaces([C|Cs], A) -> strip_spaces(Cs, [C | A]).
+decode_binary(<<C4:8, Cs/bits>>, A, B1, B2, B3) ->
+ case b64d(C4) of
+ ws -> decode_binary(Cs, A, B1, B2, B3);
+ eq when B3 =:= eq -> only_ws_binary(Cs, <<A/bits,B1:6,(B2 bsr 4):2>>);
+ eq -> only_ws_binary(Cs, <<A/bits,B1:6,B2:6,(B3 bsr 2):4>>);
+ B4 -> decode_binary(Cs, <<A/bits,B1:6,B2:6,B3:6,B4:6>>)
+ end.
-%% Skipping pad character if not at end of string. Also liberal about
-%% excess padding and skipping of other illegal (non-base64 alphabet)
-%% characters. See section 3.3 of RFC4648
-strip_illegal([], A, _Cnt) ->
+only_ws_binary(<<>>, A) ->
A;
-strip_illegal([0|Cs], A, Cnt) ->
- strip_illegal(Cs, A, Cnt);
-strip_illegal([C|Cs], A, Cnt) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- strip_illegal(Cs, A, Cnt);
- ws ->
- strip_illegal(Cs, A, Cnt);
- eq ->
- case {tail_contains_more(Cs, false), Cnt rem 4} of
- {{[], _}, 0} ->
- A; %% Ignore extra =
- {{[], true}, 2} ->
- [$=|[$=|A]]; %% 'XX=='
- {{[], _}, 3} ->
- [$=|A]; %% 'XXX='
- {{[H|T], _}, _} ->
- %% more data, skip equals
- strip_illegal(T, [H|A], Cnt+1)
- end;
- _ ->
- strip_illegal(Cs, [C|A], Cnt+1)
+only_ws_binary(<<C:8, Cs/bits>>, A) ->
+ case b64d(C) of
+ ws -> only_ws_binary(Cs, A)
end.
-%% Search the tail for more valid data and remember if we saw
-%% another equals along the way.
-tail_contains_more([], Eq) ->
- {[], Eq};
-tail_contains_more(<<>>, Eq) ->
- {<<>>, Eq};
-tail_contains_more([C|T]=More, Eq) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- tail_contains_more(T, Eq);
- ws ->
- tail_contains_more(T, Eq);
- eq ->
- tail_contains_more(T, true);
- _ ->
- {More, Eq}
+decode_list_to_string([C1 | Cs]) ->
+ case b64d(C1) of
+ ws -> decode_list_to_string(Cs);
+ B1 -> decode_list_to_string(Cs, B1)
end;
-tail_contains_more(<<C:8,T/bits>> =More, Eq) ->
- case element(C, ?DECODE_MAP) of
- bad ->
- tail_contains_more(T, Eq);
- ws ->
- tail_contains_more(T, Eq);
- eq ->
- tail_contains_more(T, true);
- _ ->
- {More, Eq}
+decode_list_to_string([]) ->
+ [].
+
+decode_list_to_string([C2 | Cs], B1) ->
+ case b64d(C2) of
+ ws -> decode_list_to_string(Cs, B1);
+ B2 -> decode_list_to_string(Cs, B1, B2)
+ end.
+
+decode_list_to_string([C3 | Cs], B1, B2) ->
+ case b64d(C3) of
+ ws -> decode_list_to_string(Cs, B1, B2);
+ B3 -> decode_list_to_string(Cs, B1, B2, B3)
+ end.
+
+decode_list_to_string([C4 | Cs], B1, B2, B3) ->
+ case b64d(C4) of
+ ws ->
+ decode_list_to_string(Cs, B1, B2, B3);
+ eq when B3 =:= eq ->
+ only_ws(Cs, binary_to_list(<<B1:6,(B2 bsr 4):2>>));
+ eq ->
+ only_ws(Cs, binary_to_list(<<B1:6,B2:6,(B3 bsr 2):4>>));
+ B4 ->
+ Bits4x6 = (B1 bsl 18) bor (B2 bsl 12) bor (B3 bsl 6) bor B4,
+ Octet1 = Bits4x6 bsr 16,
+ Octet2 = (Bits4x6 bsr 8) band 16#ff,
+ Octet3 = Bits4x6 band 16#ff,
+ [Octet1, Octet2, Octet3 | decode_list_to_string(Cs)]
+ end.
+
+only_ws([], A) ->
+ A;
+only_ws([C | Cs], A) ->
+ case b64d(C) of
+ ws -> only_ws(Cs, A)
end.
-
+
+%%%========================================================================
+%%% Internal functions
+%%%========================================================================
+
%% accessors
+-compile({inline, [{b64d, 1}]}).
+%% One-based decode map.
+b64d(X) ->
+ element(X,
+ {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, %1-15
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, %16-31
+ ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad,bad,63, %32-47
+ 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,eq,bad,bad, %48-63
+ bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
+ 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,bad,
+ bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
+ 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,
+ bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad}).
+
+-compile({inline, [{b64e, 1}]}).
b64e(X) ->
element(X+1,
{$A, $B, $C, $D, $E, $F, $G, $H, $I, $J, $K, $L, $M, $N,
@@ -404,9 +463,3 @@ b64e(X) ->
$a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n,
$o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z,
$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $+, $/}).
-
-
-b64d(X) ->
- b64d_ok(element(X, ?DECODE_MAP)).
-
-b64d_ok(I) when is_integer(I) -> I.
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index 18d7548fdc..f781312ca2 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -188,6 +188,8 @@ parse_dep_option("", T) ->
{[makedep,{makedep_output,standard_io}],T};
parse_dep_option("D", T) ->
{[makedep],T};
+parse_dep_option("MD", T) ->
+ {[makedep_side_effect],T};
parse_dep_option("F"++Opt, T0) ->
{File,T} = get_option("MF", Opt, T0),
{[makedep,{makedep_output,File}],T};
@@ -221,6 +223,7 @@ usage() ->
"the dependencies"},
{"-MP","add a phony target for each dependency"},
{"-MD","same as -M -MT file (with default 'file')"},
+ {"-MMD","generate dependencies as a side-effect"},
{"-o name","name output directory or file"},
{"-pa path","add path to the front of Erlang's code path"},
{"-pz path","add path to the end of Erlang's code path"},
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index f58cb35cea..1930c462e8 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -144,6 +144,7 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
:: dict:dict(ta(), #typeinfo{}),
exp_types=gb_sets:empty() %Exported types
:: gb_sets:set(ta()),
+ in_try_head=false :: boolean(), %In a try head.
catch_scope = none %Inside/outside try or catch
:: catch_scope()
}).
@@ -312,6 +313,10 @@ format_error({unused_var, V}) ->
io_lib:format("variable ~w is unused", [V]);
format_error({variable_in_record_def,V}) ->
io_lib:format("variable ~w in record definition", [V]);
+format_error({stacktrace_guard,V}) ->
+ io_lib:format("stacktrace variable ~w must not be used in a guard", [V]);
+format_error({stacktrace_bound,V}) ->
+ io_lib:format("stacktrace variable ~w must not be previously bound", [V]);
%% --- binaries ---
format_error({undefined_bittype,Type}) ->
io_lib:format("bit type ~tw undefined", [Type]);
@@ -3218,11 +3223,11 @@ is_module_dialyzer_option(Option) ->
try_clauses(Scs, Ccs, In, Vt, St0) ->
{Csvt0,St1} = icrt_clauses(Scs, Vt, St0),
- St2 = St1#lint{catch_scope=try_catch},
+ St2 = St1#lint{catch_scope=try_catch,in_try_head=true},
{Csvt1,St3} = icrt_clauses(Ccs, Vt, St2),
Csvt = Csvt0 ++ Csvt1,
UpdVt = icrt_export(Csvt, Vt, In, St3),
- {UpdVt,St3}.
+ {UpdVt,St3#lint{in_try_head=false}}.
%% icrt_clauses(Clauses, In, ImportVarTable, State) ->
%% {UpdVt,State}.
@@ -3239,12 +3244,29 @@ icrt_clauses(Cs, Vt, St) ->
mapfoldl(fun (C, St0) -> icrt_clause(C, Vt, St0) end, St, Cs).
icrt_clause({clause,_Line,H,G,B}, Vt0, #lint{catch_scope=Scope}=St0) ->
- {Hvt,Binvt,St1} = head(H, Vt0, St0),
- Vt1 = vtupdate(Hvt, Binvt),
- {Gvt,St2} = guard(G, vtupdate(Vt1, Vt0), St1),
- Vt2 = vtupdate(Gvt, Vt1),
- {Bvt,St3} = exprs(B, vtupdate(Vt2, Vt0), St2),
- {vtupdate(Bvt, Vt2),St3#lint{catch_scope=Scope}}.
+ Vt1 = taint_stack_var(Vt0, H, St0),
+ {Hvt,Binvt,St1} = head(H, Vt1, St0),
+ Vt2 = vtupdate(Hvt, Binvt),
+ Vt3 = taint_stack_var(Vt2, H, St0),
+ {Gvt,St2} = guard(G, vtupdate(Vt3, Vt0), St1#lint{in_try_head=false}),
+ Vt4 = vtupdate(Gvt, Vt2),
+ {Bvt,St3} = exprs(B, vtupdate(Vt4, Vt0), St2),
+ {vtupdate(Bvt, Vt4),St3#lint{catch_scope=Scope}}.
+
+taint_stack_var(Vt, Pat, #lint{in_try_head=true}) ->
+ [{tuple,_,[_,_,{var,_,Stk}]}] = Pat,
+ case Stk of
+ '_' ->
+ Vt;
+ _ ->
+ lists:map(fun({V,{bound,Used,Lines}}) when V =:= Stk ->
+ {V,{stacktrace,Used,Lines}};
+ (B) ->
+ B
+ end, Vt)
+ end;
+taint_stack_var(Vt, _Pat, #lint{in_try_head=false}) ->
+ Vt.
icrt_export(Vts, Vt, {Tag,Attrs}, St) ->
{_File,Loc} = loc(Attrs, St),
@@ -3484,6 +3506,9 @@ pat_var(V, Line, Vt, Bvt, St) ->
{[{V,{bound,used,Ls}}],[],
%% As this is matching, exported vars are risky.
add_warning(Line, {exported_var,V,From}, St)};
+ {ok,{stacktrace,_Usage,Ls}} ->
+ {[{V,{bound,used,Ls}}],[],
+ add_error(Line, {stacktrace_bound,V}, St)};
error when St#lint.recdef_top ->
{[],[{V,{bound,unused,[Line]}}],
add_error(Line, {variable_in_record_def,V}, St)};
@@ -3541,6 +3566,9 @@ expr_var(V, Line, Vt, St) ->
false ->
{[{V,{{export,From},used,Ls}}],St}
end;
+ {ok,{stacktrace,_Usage,Ls}} ->
+ {[{V,{bound,used,Ls}}],
+ add_error(Line, {stacktrace_guard,V}, St)};
error ->
{[{V,{bound,used,[Line]}}],
add_error(Line, {unbound_var,V}, St)}
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 6e72d64acc..14ca24362e 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -29,6 +29,10 @@ clause_args clause_guard clause_body
expr expr_100 expr_150 expr_160 expr_200 expr_300 expr_400 expr_500
expr_600 expr_700 expr_800
expr_max
+pat_expr pat_expr_200 pat_expr_300 pat_expr_400 pat_expr_500
+pat_expr_600 pat_expr_700 pat_expr_800
+pat_expr_max map_pat_expr record_pat_expr
+pat_argument_list pat_exprs
list tail
list_comprehension lc_expr lc_exprs
binary_comprehension
@@ -37,7 +41,7 @@ record_expr record_tuple record_field record_fields
map_expr map_tuple map_field map_field_assoc map_field_exact map_fields map_key
if_expr if_clause if_clauses case_expr cr_clause cr_clauses receive_expr
fun_expr fun_clause fun_clauses atom_or_var integer_or_var
-try_expr try_catch try_clause try_clauses
+try_expr try_catch try_clause try_clauses try_opt_stacktrace
function_call argument_list
exprs guard
atomic strings
@@ -66,7 +70,7 @@ char integer float atom string var
'spec' 'callback' % helper
dot.
-Expect 2.
+Expect 0.
Rootsymbol form.
@@ -210,7 +214,7 @@ function_clause -> atom clause_args clause_guard clause_body :
{clause,?anno('$1'),element(3, '$1'),'$2','$3','$4'}.
-clause_args -> argument_list : element(1, '$1').
+clause_args -> pat_argument_list : element(1, '$1').
clause_guard -> 'when' guard : '$2'.
clause_guard -> '$empty' : [].
@@ -275,6 +279,53 @@ expr_max -> receive_expr : '$1'.
expr_max -> fun_expr : '$1'.
expr_max -> try_expr : '$1'.
+pat_expr -> pat_expr_200 '=' pat_expr : {match,?anno('$2'),'$1','$3'}.
+pat_expr -> pat_expr_200 : '$1'.
+
+pat_expr_200 -> pat_expr_300 comp_op pat_expr_300 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_200 -> pat_expr_300 : '$1'.
+
+pat_expr_300 -> pat_expr_400 list_op pat_expr_300 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_300 -> pat_expr_400 : '$1'.
+
+pat_expr_400 -> pat_expr_400 add_op pat_expr_500 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_400 -> pat_expr_500 : '$1'.
+
+pat_expr_500 -> pat_expr_500 mult_op pat_expr_600 :
+ ?mkop2('$1', '$2', '$3').
+pat_expr_500 -> pat_expr_600 : '$1'.
+
+pat_expr_600 -> prefix_op pat_expr_700 :
+ ?mkop1('$1', '$2').
+pat_expr_600 -> map_pat_expr : '$1'.
+pat_expr_600 -> pat_expr_700 : '$1'.
+
+pat_expr_700 -> record_pat_expr : '$1'.
+pat_expr_700 -> pat_expr_800 : '$1'.
+
+pat_expr_800 -> pat_expr_max : '$1'.
+
+pat_expr_max -> var : '$1'.
+pat_expr_max -> atomic : '$1'.
+pat_expr_max -> list : '$1'.
+pat_expr_max -> binary : '$1'.
+pat_expr_max -> tuple : '$1'.
+pat_expr_max -> '(' pat_expr ')' : '$2'.
+
+map_pat_expr -> '#' map_tuple :
+ {map, ?anno('$1'),'$2'}.
+map_pat_expr -> pat_expr_max '#' map_tuple :
+ {map, ?anno('$2'),'$1','$3'}.
+map_pat_expr -> map_pat_expr '#' map_tuple :
+ {map, ?anno('$2'),'$1','$3'}.
+
+record_pat_expr -> '#' atom '.' atom :
+ {record_index,?anno('$1'),element(3, '$2'),'$4'}.
+record_pat_expr -> '#' atom record_tuple :
+ {record,?anno('$1'),element(3, '$2'),'$3'}.
list -> '[' ']' : {nil,?anno('$1')}.
list -> '[' expr tail : {cons,?anno('$1'),'$2','$3'}.
@@ -397,6 +448,10 @@ case_expr -> 'case' expr 'of' cr_clauses 'end' :
cr_clauses -> cr_clause : ['$1'].
cr_clauses -> cr_clause ';' cr_clauses : ['$1' | '$3'].
+%% FIXME: merl in syntax_tools depends on patterns in a 'case' being
+%% full expressions. Therefore, we can't use pat_expr here. There
+%% should be a better way.
+
cr_clause -> expr clause_guard clause_body :
{clause,?anno('$1'),['$1'],'$2','$3'}.
@@ -424,11 +479,11 @@ integer_or_var -> var : '$1'.
fun_clauses -> fun_clause : ['$1'].
fun_clauses -> fun_clause ';' fun_clauses : ['$1' | '$3'].
-fun_clause -> argument_list clause_guard clause_body :
+fun_clause -> pat_argument_list clause_guard clause_body :
{Args,Anno} = '$1',
{clause,Anno,'fun',Args,'$2','$3'}.
-fun_clause -> var argument_list clause_guard clause_body :
+fun_clause -> var pat_argument_list clause_guard clause_body :
{clause,element(2, '$1'),element(3, '$1'),element(1, '$2'),'$3','$4'}.
try_expr -> 'try' exprs 'of' cr_clauses try_catch :
@@ -446,24 +501,31 @@ try_catch -> 'after' exprs 'end' :
try_clauses -> try_clause : ['$1'].
try_clauses -> try_clause ';' try_clauses : ['$1' | '$3'].
-try_clause -> expr clause_guard clause_body :
+try_clause -> pat_expr clause_guard clause_body :
A = ?anno('$1'),
{clause,A,[{tuple,A,[{atom,A,throw},'$1',{var,A,'_'}]}],'$2','$3'}.
-try_clause -> atom ':' expr clause_guard clause_body :
+try_clause -> atom ':' pat_expr try_opt_stacktrace clause_guard clause_body :
A = ?anno('$1'),
- {clause,A,[{tuple,A,['$1','$3',{var,A,'_'}]}],'$4','$5'}.
-try_clause -> var ':' expr clause_guard clause_body :
+ {clause,A,[{tuple,A,['$1','$3',{var,A,'$4'}]}],'$5','$6'}.
+try_clause -> var ':' pat_expr try_opt_stacktrace clause_guard clause_body :
A = ?anno('$1'),
- {clause,A,[{tuple,A,['$1','$3',{var,A,'_'}]}],'$4','$5'}.
+ {clause,A,[{tuple,A,['$1','$3',{var,A,'$4'}]}],'$5','$6'}.
+try_opt_stacktrace -> ':' var : element(3, '$2').
+try_opt_stacktrace -> '$empty' : '_'.
argument_list -> '(' ')' : {[],?anno('$1')}.
argument_list -> '(' exprs ')' : {'$2',?anno('$1')}.
+pat_argument_list -> '(' ')' : {[],?anno('$1')}.
+pat_argument_list -> '(' pat_exprs ')' : {'$2',?anno('$1')}.
exprs -> expr : ['$1'].
exprs -> expr ',' exprs : ['$1' | '$3'].
+pat_exprs -> pat_expr : ['$1'].
+pat_exprs -> pat_expr ',' pat_exprs : ['$1' | '$3'].
+
guard -> exprs : ['$1'].
guard -> exprs ';' guard : ['$1'|'$3'].
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index 4b1d448487..0e6f49d99f 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -148,6 +148,10 @@ init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
call(Process, Label, Request) ->
call(Process, Label, Request, ?default_timeout).
+%% Optimize a common case.
+call(Process, Label, Request, Timeout) when is_pid(Process),
+ Timeout =:= infinity orelse is_integer(Timeout) andalso Timeout >= 0 ->
+ do_call(Process, Label, Request, Timeout);
call(Process, Label, Request, Timeout)
when Timeout =:= infinity; is_integer(Timeout), Timeout >= 0 ->
Fun = fun(Pid) -> do_call(Pid, Label, Request, Timeout) end,
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 48b3f5f959..1fc4c3fc0e 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -97,10 +97,9 @@ base64_otp_5635(Config) when is_list(Config) ->
<<"===">> = base64:decode(base64:encode("===")),
ok.
%%-------------------------------------------------------------------------
-%% OTP-6279: Guard needed so that function fails in a correct
-%% way for faulty input, i.e. function_clause.
+%% OTP-6279: Make sure illegal characters are rejected when decoding.
base64_otp_6279(Config) when is_list(Config) ->
- {'EXIT',{function_clause, _}} = (catch base64:decode("dGVzda==a")),
+ {'EXIT',_} = (catch base64:decode("dGVzda==a")),
ok.
%%-------------------------------------------------------------------------
%% Encode and decode big binaries.
@@ -115,48 +114,61 @@ big(Config) when is_list(Config) ->
%%-------------------------------------------------------------------------
%% Make sure illegal characters are rejected when decoding.
illegal(Config) when is_list(Config) ->
- {'EXIT',{function_clause, _}} = (catch base64:decode("()")),
+ %% A few samples with different error reasons. Nothing can be
+ %% assumed about the reason for the crash.
+ {'EXIT',_} = (catch base64:decode("()")),
+ {'EXIT',_} = (catch base64:decode(<<19:8,20:8,21:8,22:8>>)),
+ {'EXIT',_} = (catch base64:decode([19,20,21,22])),
+ {'EXIT',_} = (catch base64:decode_to_string(<<19:8,20:8,21:8,22:8>>)),
+ {'EXIT',_} = (catch base64:decode_to_string([19,20,21,22])),
ok.
%%-------------------------------------------------------------------------
%% mime_decode and mime_decode_to_string have different implementations
-%% so test both with the same input separately. Both functions have
-%% the same implementation for binary/string arguments.
+%% so test both with the same input separately.
%%
%% Test base64:mime_decode/1.
mime_decode(Config) when is_list(Config) ->
+ MimeDecode = fun(In) ->
+ Out = base64:mime_decode(In),
+ Out = base64:mime_decode(binary_to_list(In))
+ end,
%% Test correct padding
- <<"one">> = base64:mime_decode(<<"b25l">>),
- <<"on">> = base64:mime_decode(<<"b24=">>),
- <<"o">> = base64:mime_decode(<<"bw==">>),
+ <<"one">> = MimeDecode(<<"b25l">>),
+ <<"on">> = MimeDecode(<<"b24=">>),
+ <<"o">> = MimeDecode(<<"bw==">>),
%% Test 1 extra padding
- <<"one">> = base64:mime_decode(<<"b25l= =">>),
- <<"on">> = base64:mime_decode(<<"b24== =">>),
- <<"o">> = base64:mime_decode(<<"bw=== =">>),
+ <<"one">> = MimeDecode(<<"b25l= =">>),
+ <<"on">> = MimeDecode(<<"b24== =">>),
+ <<"o">> = MimeDecode(<<"bw=== =">>),
%% Test 2 extra padding
- <<"one">> = base64:mime_decode(<<"b25l===">>),
- <<"on">> = base64:mime_decode(<<"b24====">>),
- <<"o">> = base64:mime_decode(<<"bw=====">>),
+ <<"one">> = MimeDecode(<<"b25l===">>),
+ <<"on">> = MimeDecode(<<"b24====">>),
+ <<"o">> = MimeDecode(<<"bw=====">>),
%% Test misc embedded padding
- <<"one">> = base64:mime_decode(<<"b2=5l===">>),
- <<"on">> = base64:mime_decode(<<"b=24====">>),
- <<"o">> = base64:mime_decode(<<"b=w=====">>),
+ <<"one">> = MimeDecode(<<"b2=5l===">>),
+ <<"on">> = MimeDecode(<<"b=24====">>),
+ <<"o">> = MimeDecode(<<"b=w=====">>),
%% Test misc white space and illegals with embedded padding
- <<"one">> = base64:mime_decode(<<" b~2=\r\n5()l===">>),
- <<"on">> = base64:mime_decode(<<"\tb =2\"¤4=¤= ==">>),
- <<"o">> = base64:mime_decode(<<"\nb=w=====">>),
+ <<"one">> = MimeDecode(<<" b~2=\r\n5()l===">>),
+ <<"on">> = MimeDecode(<<"\tb =2\"¤4=¤= ==">>),
+ <<"o">> = MimeDecode(<<"\nb=w=====">>),
%% Two pads
<<"Aladdin:open sesame">> =
- base64:mime_decode("QWxhZGRpbjpvc()GVuIHNlc2FtZQ=="),
+ MimeDecode(<<"QWxhZGRpbjpvc()GVuIHNlc2FtZQ==">>),
%% One pad to ignore, followed by more text
- <<"Hello World!!">> = base64:mime_decode(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
+ <<"Hello World!!">> = MimeDecode(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
<<"Aladdin:open sesam">> =
- base64:mime_decode("QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft"),
+ MimeDecode(<<"QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft">>),
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
<<"0123456789!@#0^&*();:<>,. []{}">> =
- base64:mime_decode(
+ MimeDecode(
<<"MDEy MzQ1Njc4 \tOSFAIzBeJ \nio)(oKTs6 PD4sLi \r\nBbXXt9">>),
+ %% Zeroes
+ <<"012">> = MimeDecode(<<"\000M\000D\000E\000y=\000">>),
+ <<"o">> = MimeDecode(<<"bw==\000">>),
+ <<"o">> = MimeDecode(<<"bw=\000=">>),
ok.
%%-------------------------------------------------------------------------
@@ -165,39 +177,48 @@ mime_decode(Config) when is_list(Config) ->
%% Test base64:mime_decode_to_string/1.
mime_decode_to_string(Config) when is_list(Config) ->
+ MimeDecodeToString =
+ fun(In) ->
+ Out = base64:mime_decode_to_string(In),
+ Out = base64:mime_decode_to_string(binary_to_list(In))
+ end,
%% Test correct padding
- "one" = base64:mime_decode_to_string(<<"b25l">>),
- "on" = base64:mime_decode_to_string(<<"b24=">>),
- "o" = base64:mime_decode_to_string(<<"bw==">>),
+ "one" = MimeDecodeToString(<<"b25l">>),
+ "on" = MimeDecodeToString(<<"b24=">>),
+ "o" = MimeDecodeToString(<<"bw==">>),
%% Test 1 extra padding
- "one" = base64:mime_decode_to_string(<<"b25l= =">>),
- "on" = base64:mime_decode_to_string(<<"b24== =">>),
- "o" = base64:mime_decode_to_string(<<"bw=== =">>),
+ "one" = MimeDecodeToString(<<"b25l= =">>),
+ "on" = MimeDecodeToString(<<"b24== =">>),
+ "o" = MimeDecodeToString(<<"bw=== =">>),
%% Test 2 extra padding
- "one" = base64:mime_decode_to_string(<<"b25l===">>),
- "on" = base64:mime_decode_to_string(<<"b24====">>),
- "o" = base64:mime_decode_to_string(<<"bw=====">>),
+ "one" = MimeDecodeToString(<<"b25l===">>),
+ "on" = MimeDecodeToString(<<"b24====">>),
+ "o" = MimeDecodeToString(<<"bw=====">>),
%% Test misc embedded padding
- "one" = base64:mime_decode_to_string(<<"b2=5l===">>),
- "on" = base64:mime_decode_to_string(<<"b=24====">>),
- "o" = base64:mime_decode_to_string(<<"b=w=====">>),
+ "one" = MimeDecodeToString(<<"b2=5l===">>),
+ "on" = MimeDecodeToString(<<"b=24====">>),
+ "o" = MimeDecodeToString(<<"b=w=====">>),
%% Test misc white space and illegals with embedded padding
- "one" = base64:mime_decode_to_string(<<" b~2=\r\n5()l===">>),
- "on" = base64:mime_decode_to_string(<<"\tb =2\"¤4=¤= ==">>),
- "o" = base64:mime_decode_to_string(<<"\nb=w=====">>),
+ "one" = MimeDecodeToString(<<" b~2=\r\n5()l===">>),
+ "on" = MimeDecodeToString(<<"\tb =2\"¤4=¤= ==">>),
+ "o" = MimeDecodeToString(<<"\nb=w=====">>),
%% Two pads
"Aladdin:open sesame" =
- base64:mime_decode_to_string("QWxhZGRpbjpvc()GVuIHNlc2FtZQ=="),
+ MimeDecodeToString(<<"QWxhZGRpbjpvc()GVuIHNlc2FtZQ==">>),
%% One pad to ignore, followed by more text
- "Hello World!!" = base64:mime_decode_to_string(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
+ "Hello World!!" = MimeDecodeToString(<<"SGVsb)(G8gV29ybGQ=h IQ= =">>),
%% No pad
"Aladdin:open sesam" =
- base64:mime_decode_to_string("QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft"),
+ MimeDecodeToString(<<"QWxhZGRpbjpvcG¤\")(VuIHNlc2Ft">>),
%% Encoded base 64 strings may be divided by non base 64 chars.
%% In this cases whitespaces.
"0123456789!@#0^&*();:<>,. []{}" =
- base64:mime_decode_to_string(
+ MimeDecodeToString(
<<"MDEy MzQ1Njc4 \tOSFAIzBeJ \nio)(oKTs6 PD4sLi \r\nBbXXt9">>),
+ %% Zeroes
+ "012" = MimeDecodeToString(<<"\000M\000D\000E\000y=\000">>),
+ "o" = MimeDecodeToString(<<"bw==\000">>),
+ "o" = MimeDecodeToString(<<"bw=\000=">>),
ok.
%%-------------------------------------------------------------------------
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index b76bece07f..5efffc6a5c 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -66,7 +66,8 @@
otp_11851/1,otp_11879/1,otp_13230/1,
record_errors/1, otp_11879_cont/1,
non_latin1_module/1, otp_14323/1,
- get_stacktrace/1, otp_14285/1, otp_14378/1]).
+ get_stacktrace/1, stacktrace_syntax/1,
+ otp_14285/1, otp_14378/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -87,7 +88,7 @@ all() ->
maps, maps_type, maps_parallel_match,
otp_11851, otp_11879, otp_13230,
record_errors, otp_11879_cont, non_latin1_module, otp_14323,
- get_stacktrace, otp_14285, otp_14378].
+ get_stacktrace, stacktrace_syntax, otp_14285, otp_14378].
groups() ->
[{unused_vars_warn, [],
@@ -4129,6 +4130,40 @@ get_stacktrace(Config) ->
run(Config, Ts),
ok.
+stacktrace_syntax(Config) ->
+ Ts = [{guard,
+ <<"t1() ->
+ try error(foo)
+ catch _:_:Stk when is_number(Stk) -> ok
+ end.
+ ">>,
+ [],
+ {errors,[{3,erl_lint,{stacktrace_guard,'Stk'}}],[]}},
+ {bound,
+ <<"t1() ->
+ Stk = [],
+ try error(foo)
+ catch _:_:Stk -> ok
+ end.
+ ">>,
+ [],
+ {errors,[{4,erl_lint,{stacktrace_bound,'Stk'}}],[]}},
+ {guard_and_bound,
+ <<"t1() ->
+ Stk = [],
+ try error(foo)
+ catch _:_:Stk when is_integer(Stk) -> ok
+ end.
+ ">>,
+ [],
+ {errors,[{4,erl_lint,{stacktrace_bound,'Stk'}},
+ {4,erl_lint,{stacktrace_guard,'Stk'}}],[]}}
+ ],
+
+ run(Config, Ts),
+ ok.
+
+
%% Unicode atoms.
otp_14285(Config) ->
%% A small sample of all the errors and warnings in module erl_lint.
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index ef4f9faad9..3d3241b33d 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -29,6 +29,9 @@
basic_stats_uniform_1/1, basic_stats_uniform_2/1,
basic_stats_standard_normal/1,
basic_stats_normal/1,
+ stats_standard_normal_box_muller/1,
+ stats_standard_normal_box_muller_2/1,
+ stats_standard_normal/1,
uniform_real_conv/1,
plugin/1, measure/1,
reference_jump_state/1, reference_jump_procdict/1]).
@@ -57,7 +60,10 @@ all() ->
groups() ->
[{basic_stats, [parallel],
[basic_stats_uniform_1, basic_stats_uniform_2,
- basic_stats_standard_normal]},
+ basic_stats_standard_normal,
+ stats_standard_normal_box_muller,
+ stats_standard_normal_box_muller_2,
+ stats_standard_normal]},
{reference_jump, [parallel],
[reference_jump_state, reference_jump_procdict]}].
@@ -410,6 +416,206 @@ normal_s(Mean, Variance, State0) when Mean == 0, Variance == 1 ->
normal_s(Mean, Variance, State0) ->
rand:normal_s(Mean, Variance, State0).
+
+
+-dialyzer({no_improper_lists, stats_standard_normal_box_muller/1}).
+stats_standard_normal_box_muller(Config) when is_list(Config) ->
+ try math:erfc(1.0) of
+ _ ->
+ TwoPi = 2.0 * math:pi(),
+ NormalS =
+ fun
+ ([S0]) ->
+ {U1, S1} = rand:uniform_real_s(S0),
+ R = math:sqrt(-2.0 * math:log(U1)),
+ {U2, S2} = rand:uniform_s(S1),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ {Z0, [S2|Z1]};
+ ([S|Z]) ->
+ {Z, [S]}
+ end,
+ State = [rand:seed(exrop)],
+ stats_standard_normal(NormalS, State)
+ catch error:_ ->
+ {skip, "math:erfc/1 not supported"}
+ end.
+
+-dialyzer({no_improper_lists, stats_standard_normal_box_muller_2/1}).
+stats_standard_normal_box_muller_2(Config) when is_list(Config) ->
+ try math:erfc(1.0) of
+ _ ->
+ TwoPi = 2.0 * math:pi(),
+ NormalS =
+ fun
+ ([S0]) ->
+ {U0, S1} = rand:uniform_s(S0),
+ U1 = 1.0 - U0,
+ R = math:sqrt(-2.0 * math:log(U1)),
+ {U2, S2} = rand:uniform_s(S1),
+ T = TwoPi * U2,
+ Z0 = R * math:cos(T),
+ Z1 = R * math:sin(T),
+ {Z0, [S2|Z1]};
+ ([S|Z]) ->
+ {Z, [S]}
+ end,
+ State = [rand:seed(exrop)],
+ stats_standard_normal(NormalS, State)
+ catch error:_ ->
+ {skip, "math:erfc/1 not supported"}
+ end.
+
+
+stats_standard_normal(Config) when is_list(Config) ->
+ try math:erfc(1.0) of
+ _ ->
+ stats_standard_normal(
+ fun rand:normal_s/1, rand:seed_s(exrop))
+ catch error:_ ->
+ {skip, "math:erfc/1 not supported"}
+ end.
+%%
+stats_standard_normal(Fun, S) ->
+%%%
+%%% ct config:
+%%% {rand_SUITE, [{stats_standard_normal,[{seconds, 8}, {std_devs, 4.2}]}]}.
+%%%
+ Seconds = ct:get_config({?MODULE, ?FUNCTION_NAME, seconds}, 8),
+ StdDevs =
+ ct:get_config(
+ {?MODULE, ?FUNCTION_NAME, std_devs},
+ 4.2), % probability erfc(4.2/sqrt(2)) (1/37465) to fail a bucket
+%%%
+ ct:timetrap({seconds, Seconds + 120}),
+ %% Buckets is chosen to get a range where the the probability to land
+ %% in the top catch-all bucket is not vanishingly low, but with
+ %% these values it is about 1/25 of the probability for the low bucket
+ %% (closest to 0).
+ %%
+ %% Rounds is calculated so the expected value for the low
+ %% bucket will be at least TargetHits.
+ %%
+ InvDelta = 512,
+ Buckets = 4 * InvDelta, % 4 std devs range
+ TargetHits = 1024,
+ Sqrt2 = math:sqrt(2.0),
+ W = InvDelta * Sqrt2,
+ P0 = math:erf(1 / W),
+ Rounds = TargetHits * ceil(1.0 / P0),
+ Histogram = array:new({default, 0}),
+ StopTime = erlang:monotonic_time(second) + Seconds,
+ ct:pal(
+ "Running standard normal test against ~w std devs for ~w seconds...",
+ [StdDevs, Seconds]),
+ {PositiveHistogram, NegativeHistogram, Outlier, TotalRounds} =
+ stats_standard_normal(
+ InvDelta, Buckets, Histogram, Histogram, 0.0,
+ Fun, S, Rounds, StopTime, Rounds, 0),
+ Precision = math:sqrt(TotalRounds * P0) / StdDevs,
+ TopP = math:erfc(Buckets / W),
+ TopPrecision = math:sqrt(TotalRounds * TopP) / StdDevs,
+ OutlierProbability = math:erfc(Outlier / Sqrt2) * TotalRounds,
+ InvOP = 1.0 / OutlierProbability,
+ ct:pal(
+ "Total rounds: ~w, tolerance: 1/~.2f..1/~.2f, "
+ "outlier: ~.2f, probability 1/~.2f.",
+ [TotalRounds, Precision, TopPrecision, Outlier, InvOP]),
+ {TotalRounds, [], []} =
+ {TotalRounds,
+ check_histogram(
+ W, TotalRounds, StdDevs, PositiveHistogram, Buckets),
+ check_histogram(
+ W, TotalRounds, StdDevs, NegativeHistogram, Buckets)},
+ %% If the probability for getting this Outlier is lower than 1/50,
+ %% then this is fishy!
+ true = (1/50 =< OutlierProbability),
+ {comment, {tp, TopPrecision, op, InvOP}}.
+%%
+stats_standard_normal(
+ InvDelta, Buckets, PositiveHistogram, NegativeHistogram, Outlier,
+ Fun, S, 0, StopTime, Rounds, TotalRounds) ->
+ case erlang:monotonic_time(second) of
+ Now when Now < StopTime ->
+ stats_standard_normal(
+ InvDelta, Buckets,
+ PositiveHistogram, NegativeHistogram, Outlier,
+ Fun, S, Rounds, StopTime, Rounds, TotalRounds + Rounds);
+ _ ->
+ {PositiveHistogram, NegativeHistogram,
+ Outlier, TotalRounds + Rounds}
+ end;
+stats_standard_normal(
+ InvDelta, Buckets, PositiveHistogram, NegativeHistogram, Outlier,
+ Fun, S, Count, StopTime, Rounds, TotalRounds) ->
+ case Fun(S) of
+ {X, NewS} when 0.0 =< X ->
+ Bucket = min(Buckets, floor(X * InvDelta)),
+ stats_standard_normal(
+ InvDelta, Buckets,
+ increment_bucket(Bucket, PositiveHistogram),
+ NegativeHistogram, max(Outlier, X),
+ Fun, NewS, Count - 1, StopTime, Rounds, TotalRounds);
+ {MinusX, NewS} ->
+ X = -MinusX,
+ Bucket = min(Buckets, floor(X * InvDelta)),
+ stats_standard_normal(
+ InvDelta, Buckets,
+ PositiveHistogram,
+ increment_bucket(Bucket, NegativeHistogram), max(Outlier, X),
+ Fun, NewS, Count - 1, StopTime, Rounds, TotalRounds)
+ end.
+
+increment_bucket(Bucket, Array) ->
+ array:set(Bucket, array:get(Bucket, Array) + 1, Array).
+
+check_histogram(W, Rounds, StdDevs, Histogram, Buckets) ->
+ %%PrevBucket = 512,
+ %%Bucket = PrevBucket - 1,
+ %%P = 0.5 * math:erfc(PrevBucket / W),
+ TargetP = 0.5 * math:erfc(Buckets / W),
+ P = 0.0,
+ N = 0,
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Buckets, Buckets, P, N).
+%%
+check_histogram(
+ _W, _Rounds, _StdDevs, _Histogram, _TargetP,
+ 0, _PrevBucket, _PrevP, _PrevN) ->
+ [];
+check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket, PrevBucket, PrevP, PrevN) ->
+ N = PrevN + array:get(Bucket, Histogram),
+ P = 0.5 * math:erfc(Bucket / W),
+ BucketP = P - PrevP,
+ if
+ TargetP =< BucketP ->
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket - 1, PrevBucket, PrevP, N);
+ true ->
+ Exp = BucketP * Rounds,
+ Var = Rounds * BucketP*(1.0 - BucketP),
+ Threshold = StdDevs * math:sqrt(Var),
+ LowerLimit = floor(Exp - Threshold),
+ UpperLimit = ceil(Exp + Threshold),
+ if
+ N < LowerLimit; UpperLimit < N ->
+ [#{bucket => {Bucket, PrevBucket}, n => N, exp => Exp,
+ lower => LowerLimit, upper => UpperLimit} |
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket - 1, Bucket, P, 0)];
+ true ->
+ check_histogram(
+ W, Rounds, StdDevs, Histogram, TargetP,
+ Bucket - 1, Bucket, P, 0)
+ end
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% White box test of the conversion to float
diff --git a/lib/stdlib/test/stdlib.spec b/lib/stdlib/test/stdlib.spec
index 91712b8963..1adec67ac9 100644
--- a/lib/stdlib/test/stdlib.spec
+++ b/lib/stdlib/test/stdlib.spec
@@ -1,2 +1,3 @@
{suites,"../stdlib_test",all}.
-{skip_suites,"../stdlib_test",stdlib_bench_SUITE, "bench only"}.
+{skip_groups,"../stdlib_test",stdlib_bench_SUITE,[base64,gen_server,unicode],
+ "Benchmark only"}.
diff --git a/lib/stdlib/test/stdlib_bench.spec b/lib/stdlib/test/stdlib_bench.spec
index a5d1e1db80..f82f1ab9b3 100644
--- a/lib/stdlib/test/stdlib_bench.spec
+++ b/lib/stdlib/test/stdlib_bench.spec
@@ -5,3 +5,5 @@
{skip_suites,"../stdlib_test",string_SUITE, "bench only"}.
{suites,"../stdlib_test",[stdlib_bench_SUITE]}.
+{skip_groups,"../stdlib_test",stdlib_bench_SUITE,[gen_server_comparison],
+ "Not a benchmark"}.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE.erl b/lib/stdlib/test/stdlib_bench_SUITE.erl
index 8670e7029c..cc7e070dbd 100644
--- a/lib/stdlib/test/stdlib_bench_SUITE.erl
+++ b/lib/stdlib/test/stdlib_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
%%
-module(stdlib_bench_SUITE).
-compile([export_all, nowarn_export_all]).
+-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -28,14 +29,35 @@ suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
all() ->
- [{group,unicode}].
+ [{group,unicode},{group,base64},
+ {group,gen_server},{group,gen_server_comparison}].
groups() ->
[{unicode,[{repeat,5}],
[norm_nfc_list, norm_nfc_deep_l, norm_nfc_binary,
string_lexemes_list, string_lexemes_binary
- ]}].
+ ]},
+ {base64,[{repeat,5}],
+ [decode_binary, decode_binary_to_string,
+ decode_list, decode_list_to_string,
+ encode_binary, encode_binary_to_string,
+ encode_list, encode_list_to_string,
+ mime_binary_decode, mime_binary_decode_to_string,
+ mime_list_decode, mime_list_decode_to_string]},
+ {gen_server, [{repeat,5}],
+ [simple, simple_timer, simple_mon, simple_timer_mon,
+ generic, generic_timer]},
+ {gen_server_comparison, [],
+ [single_small, single_medium, single_big,
+ sched_small, sched_medium, sched_big,
+ multi_small, multi_medium, multi_big]}].
+init_per_group(GroupName, Config) when GroupName =:= gen_server;
+ GroupName =:= gen_server_comparison ->
+ DataDir = ?config(data_dir, Config),
+ Files = filelib:wildcard(filename:join(DataDir, "{simple,generic}*.erl")),
+ _ = [{ok, _} = compile:file(File) || File <- Files],
+ Config;
init_per_group(_GroupName, Config) ->
Config.
@@ -105,3 +127,301 @@ norm_data(Config) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+decode_binary(_Config) ->
+ test(decode, encoded_binary()).
+
+decode_binary_to_string(_Config) ->
+ test(decode_to_string, encoded_binary()).
+
+decode_list(_Config) ->
+ test(decode, encoded_list()).
+
+decode_list_to_string(_Config) ->
+ test(decode_to_string, encoded_list()).
+
+encode_binary(_Config) ->
+ test(encode, binary()).
+
+encode_binary_to_string(_Config) ->
+ test(encode_to_string, binary()).
+
+encode_list(_Config) ->
+ test(encode, list()).
+
+encode_list_to_string(_Config) ->
+ test(encode_to_string, list()).
+
+mime_binary_decode(_Config) ->
+ test(mime_decode, encoded_binary()).
+
+mime_binary_decode_to_string(_Config) ->
+ test(mime_decode_to_string, encoded_binary()).
+
+mime_list_decode(_Config) ->
+ test(mime_decode, encoded_list()).
+
+mime_list_decode_to_string(_Config) ->
+ test(mime_decode_to_string, encoded_list()).
+
+-define(SIZE, 10000).
+-define(N, 1000).
+
+encoded_binary() ->
+ list_to_binary(encoded_list()).
+
+encoded_list() ->
+ L = random_byte_list(round(?SIZE*0.75)),
+ base64:encode_to_string(L).
+
+binary() ->
+ list_to_binary(list()).
+
+list() ->
+ random_byte_list(?SIZE).
+
+test(Func, Data) ->
+ F = fun() -> loop(?N, Func, Data) end,
+ {Time, ok} = timer:tc(fun() -> lspawn(F) end),
+ report_base64(Time).
+
+loop(0, _F, _D) -> garbage_collect(), ok;
+loop(N, F, D) ->
+ _ = base64:F(D),
+ loop(N - 1, F, D).
+
+lspawn(Fun) ->
+ {Pid, Ref} = spawn_monitor(fun() -> exit(Fun()) end),
+ receive
+ {'DOWN', Ref, process, Pid, Rep} -> Rep
+ end.
+
+report_base64(Time) ->
+ Tps = round((?N*1000000)/Time),
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{suite, "stdlib_base64"},
+ {value, Tps}]}),
+ Tps.
+
+%% Copied from base64_SUITE.erl.
+
+random_byte_list(N) ->
+ random_byte_list(N, []).
+
+random_byte_list(0, Acc) ->
+ Acc;
+random_byte_list(N, Acc) ->
+ random_byte_list(N-1, [rand:uniform(255)|Acc]).
+
+make_big_binary(N) ->
+ list_to_binary(mbb(N, [])).
+
+mbb(N, Acc) when N > 256 ->
+ B = list_to_binary(lists:seq(0, 255)),
+ mbb(N - 256, [B | Acc]);
+mbb(N, Acc) ->
+ B = list_to_binary(lists:seq(0, N-1)),
+ lists:reverse(Acc, B).
+
+simple(Config) when is_list(Config) ->
+ do_tests(simple, single_small).
+
+simple_timer(Config) when is_list(Config) ->
+ do_tests(simple_timer, single_small).
+
+simple_mon(Config) when is_list(Config) ->
+ do_tests(simple_mon, single_small).
+
+simple_timer_mon(Config) when is_list(Config) ->
+ do_tests(simple_timer_mon, single_small).
+
+generic(Config) when is_list(Config) ->
+ do_tests(generic, single_small).
+
+generic_timer(Config) when is_list(Config) ->
+ do_tests(generic_timer, single_small).
+
+single_small(Config) when is_list(Config) ->
+ comparison(single_small).
+
+single_medium(Config) when is_list(Config) ->
+ comparison(single_medium).
+
+single_big(Config) when is_list(Config) ->
+ comparison(single_big).
+
+sched_small(Config) when is_list(Config) ->
+ comparison(sched_small).
+
+sched_medium(Config) when is_list(Config) ->
+ comparison(sched_medium).
+
+sched_big(Config) when is_list(Config) ->
+ comparison(sched_big).
+
+multi_small(Config) when is_list(Config) ->
+ comparison(multi_small).
+
+multi_medium(Config) when is_list(Config) ->
+ comparison(multi_medium).
+
+multi_big(Config) when is_list(Config) ->
+ comparison(multi_big).
+
+comparison(Kind) ->
+ Simple0 = do_tests(simple, Kind),
+ SimpleTimer0 = do_tests(simple_timer, Kind),
+ SimpleMon0 = do_tests(simple_mon, Kind),
+ SimpleTimerMon0 = do_tests(simple_timer_mon, Kind),
+ Generic0 = do_tests(generic, Kind),
+ GenericTimer0 = do_tests(generic_timer, Kind),
+ %% Normalize
+ Simple = norm(Simple0, Simple0),
+ SimpleTimer = norm(SimpleTimer0, Simple0),
+ SimpleMon = norm(SimpleMon0, Simple0),
+ SimpleTimerMon = norm(SimpleTimerMon0, Simple0),
+ Generic = norm(Generic0, Simple0),
+ GenericTimer = norm(GenericTimer0, Simple0),
+ {Parallelism, _N, Message} = bench_params(Kind),
+ Wordsize = erlang:system_info(wordsize),
+ MSize = Wordsize * erts_debug:flat_size(Message),
+ What = io_lib:format("#parallel gen_server instances: ~.4w, "
+ "message flat size: ~.5w bytes",
+ [Parallelism, MSize]),
+ C = io_lib:format("~s: "
+ "Simple: ~s Simple+Timer: ~s "
+ "Simple+Monitor: ~s Simple+Timer+Monitor: ~s "
+ "Generic: ~s Generic+Timer: ~s",
+ [What, Simple, SimpleTimer, SimpleMon, SimpleTimerMon,
+ Generic, GenericTimer]),
+ {comment, C}.
+
+norm(T, Ref) ->
+ io_lib:format("~.2f", [T/Ref]).
+
+do_tests(Test, ParamSet) ->
+ {Client, ServerMod} = bench(Test),
+ {Parallelism, N, Message} = bench_params(ParamSet),
+ Fun = create_clients(N, Message, ServerMod, Client, Parallelism),
+ Time = run_test(Fun),
+ TimesPerTest = 5,
+ PerSecond = Parallelism * TimesPerTest * round((1000 * N) / Time),
+ ct_event:notify(#event{name = benchmark_data,
+ data = [{suite,"stdlib_gen_server"},
+ {value,PerSecond}]}),
+ Time.
+
+simple_client(0, _, _P) ->
+ ok;
+simple_client(N, M, P) ->
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ _ = simple_server:reply(P, M),
+ simple_client(N-1, M, P).
+
+simple_client_timer(0, _, _P) ->
+ ok;
+simple_client_timer(N, M, P) ->
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ _ = simple_server_timer:reply(P, M),
+ simple_client_timer(N-1, M, P).
+
+simple_client_mon(0, _, _P) ->
+ ok;
+simple_client_mon(N, M, P) ->
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ _ = simple_server_mon:reply(P, M),
+ simple_client_mon(N-1, M, P).
+
+simple_client_timer_mon(0, _, _P) ->
+ ok;
+simple_client_timer_mon(N, M, P) ->
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ _ = simple_server_timer_mon:reply(P, M),
+ simple_client_timer_mon(N-1, M, P).
+
+generic_client(0, _, _P) ->
+ ok;
+generic_client(N, M, P) ->
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ _ = generic_server:reply(P, M),
+ generic_client(N-1, M, P).
+
+generic_timer_client(0, _, _P) ->
+ ok;
+generic_timer_client(N, M, P) ->
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ _ = generic_server_timer:reply(P, M),
+ generic_timer_client(N-1, M, P).
+
+bench(simple) ->
+ {fun simple_client/3, simple_server};
+bench(simple_timer) ->
+ {fun simple_client_timer/3, simple_server_timer};
+bench(simple_mon) ->
+ {fun simple_client_mon/3, simple_server_mon};
+bench(simple_timer_mon) ->
+ {fun simple_client_timer_mon/3, simple_server_timer_mon};
+bench(generic) ->
+ {fun generic_client/3, generic_server};
+bench(generic_timer) ->
+ {fun generic_timer_client/3, generic_server_timer}.
+
+%% -> {Parallelism, NumberOfMessages, MessageTerm}
+bench_params(single_small) -> {1, 700000, small()};
+bench_params(single_medium) -> {1, 350000, medium()};
+bench_params(single_big) -> {1, 70000, big()};
+bench_params(sched_small) -> {parallelism(), 200000, small()};
+bench_params(sched_medium) -> {parallelism(), 100000, medium()};
+bench_params(sched_big) -> {parallelism(), 20000, big()};
+bench_params(multi_small) -> {400, 2000, small()};
+bench_params(multi_medium) -> {400, 1000, medium()};
+bench_params(multi_big) -> {400, 200, big()}.
+
+small() ->
+ small.
+
+medium() ->
+ lists:seq(1, 50).
+
+big() ->
+ lists:seq(1, 1000).
+
+parallelism() ->
+ case erlang:system_info(multi_scheduling) of
+ enabled -> erlang:system_info(schedulers_online);
+ _ -> 1
+ end.
+
+create_clients(N, M, ServerMod, Client, Parallel) ->
+ fun() ->
+ State = term,
+ ServerPid = ServerMod:start(State),
+ PidRefs = [spawn_monitor(fun() -> Client(N, M, ServerPid) end) ||
+ _ <- lists:seq(1, Parallel)],
+ _ = [receive {'DOWN', Ref, _, _, _} -> ok end ||
+ {_Pid, Ref} <- PidRefs],
+ ok = ServerMod:stop(ServerPid)
+ end.
+
+run_test(Test) ->
+ {T1, _} = statistics(runtime),
+ Test(),
+ {T2, _} = statistics(runtime),
+ T2 - T1.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl
new file mode 100644
index 0000000000..abd61dcdef
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server.erl
@@ -0,0 +1,31 @@
+-module(generic_server).
+
+-export([start/1, reply/2, stop/1]).
+
+-export([handle_call/3, handle_cast/2, init/1, terminate/2]).
+
+-behaviour(gen_server).
+
+-define(GEN_SERVER, gen_server).
+
+start(State) ->
+ {ok, Pid} = ?GEN_SERVER:start(?MODULE, State, []),
+ Pid.
+
+init(State) ->
+ {ok, State}.
+
+stop(P) ->
+ ok = ?GEN_SERVER:stop(P).
+
+reply(S, M) ->
+ _M = ?GEN_SERVER:call(S, {reply, M}, infinity).
+
+handle_call({reply, M}, _From, State) ->
+ {reply, M, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl
new file mode 100644
index 0000000000..0faa30207d
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/generic_server_timer.erl
@@ -0,0 +1,31 @@
+-module(generic_server_timer).
+
+-export([start/1, reply/2, stop/1]).
+
+-export([handle_call/3, handle_cast/2, init/1, terminate/2]).
+
+-behaviour(gen_server).
+
+-define(GEN_SERVER, gen_server).
+
+start(State) ->
+ {ok, Pid} = ?GEN_SERVER:start(?MODULE, State, []),
+ Pid.
+
+init(State) ->
+ {ok, State}.
+
+stop(P) ->
+ ok = ?GEN_SERVER:stop(P).
+
+reply(S, M) ->
+ ?GEN_SERVER:call(S, {reply, M}).
+
+handle_call({reply, M}, _From, State) ->
+ {reply, M, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl
new file mode 100644
index 0000000000..bd43f686e8
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server.erl
@@ -0,0 +1,31 @@
+-module(simple_server).
+
+%% Local process. No timer. No monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, M} ->
+ P ! M,
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ P ! {reply, self(), M},
+ receive
+ M ->
+ M
+ end.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl
new file mode 100644
index 0000000000..9b5ace5586
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_mon.erl
@@ -0,0 +1,33 @@
+-module(simple_server_mon).
+
+%% Local process. No timer. Monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, Mref, M} ->
+ P ! {ok, Mref, M},
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ Mref = erlang:monitor(process, P),
+ P ! {reply, self(), Mref, M},
+ receive
+ {ok, Mref, M} ->
+ erlang:demonitor(Mref, [flush]),
+ ok
+ end.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl
new file mode 100644
index 0000000000..82381e1fdf
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer.erl
@@ -0,0 +1,33 @@
+-module(simple_server_timer).
+
+%% Local process. Timer. No monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, M} ->
+ P ! M,
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ P ! {reply, self(), M},
+ receive
+ M ->
+ M
+ after 100 ->
+ exit(fel)
+ end.
diff --git a/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl
new file mode 100644
index 0000000000..6124ca29c2
--- /dev/null
+++ b/lib/stdlib/test/stdlib_bench_SUITE_data/simple_server_timer_mon.erl
@@ -0,0 +1,35 @@
+-module(simple_server_timer_mon).
+
+%% Local process. Timer. Monitor.
+
+-export([start/1, reply/2, stop/1]).
+
+start(State) ->
+ spawn(fun() -> loop(State) end).
+
+stop(P) ->
+ P ! {stop, self()},
+ receive
+ ok ->
+ ok
+ end.
+
+loop(S) ->
+ receive
+ {reply, P, Mref, M} ->
+ P ! {ok, Mref, M},
+ loop(S);
+ {stop, P} ->
+ P ! ok
+ end.
+
+reply(P, M) ->
+ Mref = erlang:monitor(process, P),
+ P ! {reply, self(), Mref, M},
+ receive
+ {ok, Mref, M} ->
+ erlang:demonitor(Mref, [flush]),
+ ok
+ after 100 ->
+ exit(fel)
+ end.
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 48db5dc900..69d258c2f0 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.4.2
+STDLIB_VSN = 3.4.3
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index 8c91f01e3b..bd2bcde2c2 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 2.1.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index 40ddd2b22a..f03f326278 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -774,9 +774,17 @@ lay_2(Node, Ctxt) ->
class_qualifier ->
Ctxt1 = set_prec(Ctxt, max_prec()),
D1 = lay(erl_syntax:class_qualifier_argument(Node), Ctxt1),
- D2 = lay(erl_syntax:class_qualifier_body(Node), Ctxt1),
- beside(D1, beside(text(":"), D2));
-
+ D2 = lay(erl_syntax:class_qualifier_body(Node), Ctxt1),
+ Stacktrace = erl_syntax:class_qualifier_stacktrace(Node),
+ case erl_syntax:variable_name(Stacktrace) of
+ '_' ->
+ beside(D1, beside(text(":"), D2));
+ _ ->
+ D3 = lay(erl_syntax:class_qualifier_stacktrace(Node),
+ Ctxt1),
+ beside(D1, beside(beside(text(":"), D2),
+ beside(text(":"), D3)))
+ end;
comment ->
D = stack_comment_lines(
erl_syntax:comment_text(Node)),
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 9b2b503762..ed552b73df 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -342,8 +342,10 @@
typed_record_field_body/1,
typed_record_field_type/1,
class_qualifier/2,
+ class_qualifier/3,
class_qualifier_argument/1,
class_qualifier_body/1,
+ class_qualifier_stacktrace/1,
tuple/1,
tuple_elements/1,
tuple_size/1,
@@ -3884,7 +3886,7 @@ fold_try_clause({clause, Pos, [P], Guard, Body}) ->
class_qualifier ->
{tuple, Pos, [class_qualifier_argument(P),
class_qualifier_body(P),
- {var, Pos, '_'}]};
+ class_qualifier_stacktrace(P)]};
_ ->
{tuple, Pos, [{atom, Pos, throw}, P, {var, Pos, '_'}]}
end,
@@ -3896,9 +3898,9 @@ unfold_try_clauses(Cs) ->
unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw}, V, _]}],
Guard, Body}) ->
{clause, Pos, [V], Guard, Body};
-unfold_try_clause({clause, Pos, [{tuple, _, [C, V, _]}],
+unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}],
Guard, Body}) ->
- {clause, Pos, [class_qualifier(C, V)], Guard, Body}.
+ {clause, Pos, [class_qualifier(C, V, Stacktrace)], Guard, Body}.
%% =====================================================================
@@ -6725,9 +6727,12 @@ try_expr_after(Node) ->
%%
%% @see class_qualifier_argument/1
%% @see class_qualifier_body/1
+%% @see class_qualifier_stacktrace/1
%% @see try_expr/4
--record(class_qualifier, {class :: syntaxTree(), body :: syntaxTree()}).
+-record(class_qualifier, {class :: syntaxTree(),
+ body :: syntaxTree(),
+ stacktrace :: syntaxTree()}).
%% type(Node) = class_qualifier
%% data(Node) = #class_qualifier{class :: Class, body :: Body}
@@ -6737,8 +6742,27 @@ try_expr_after(Node) ->
-spec class_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree().
class_qualifier(Class, Body) ->
+ Underscore = {var, get_pos(Body), '_'},
tree(class_qualifier,
- #class_qualifier{class = Class, body = Body}).
+ #class_qualifier{class = Class, body = Body,
+ stacktrace = Underscore}).
+
+%% =====================================================================
+%% @doc Creates an abstract class qualifier. The result represents
+%% "<code><em>Class</em>:<em>Body</em>:<em>Stacktrace</em></code>".
+%%
+%% @see class_qualifier_argument/1
+%% @see class_qualifier_body/1
+%% @see try_expr/4
+
+-spec class_qualifier(syntaxTree(), syntaxTree(), syntaxTree()) ->
+ syntaxTree().
+
+class_qualifier(Class, Body, Stacktrace) ->
+ tree(class_qualifier,
+ #class_qualifier{class = Class,
+ body = Body,
+ stacktrace = Stacktrace}).
%% =====================================================================
@@ -6763,6 +6787,16 @@ class_qualifier_argument(Node) ->
class_qualifier_body(Node) ->
(data(Node))#class_qualifier.body.
+%% =====================================================================
+%% @doc Returns the stacktrace subtree of a `class_qualifier' node.
+%%
+%% @see class_qualifier/2
+
+-spec class_qualifier_stacktrace(syntaxTree()) -> syntaxTree().
+
+class_qualifier_stacktrace(Node) ->
+ (data(Node))#class_qualifier.stacktrace.
+
%% =====================================================================
%% @doc Creates an abstract "implicit fun" expression. If
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index e0880d61ee..8d37c40742 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.1.3
+SYNTAX_TOOLS_VSN = 2.1.4
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 3eaa2058a0..1edc08c9cd 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 2.11.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 2.11</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index d9efadf64a..6b93d63182 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -885,7 +885,6 @@ resulting regexp is surrounded by \\_< and \\_>."
"append"
"append_element"
"await_proc_exit"
- "await_sched_wall_time_modifications"
"bump_reductions"
"call_on_load_function"
"cancel_timer"
@@ -923,7 +922,6 @@ resulting regexp is surrounded by \\_< and \\_>."
"function_exported"
"garbage_collect_message_area"
"gather_gc_info_result"
- "gather_sched_wall_time_result"
"get_cookie"
"get_module_info"
"get_stacktrace"
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 801bbc7461..bf5faa165d 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -2456,7 +2456,9 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
Pattern = {#bump{module=Module,line='$1',_='_'},'$2'},
MS = [{Pattern,[{is_integer,'$1'},{'>','$1',0}],[{{'$1','$2'}}]}],
- CovLines = lists:keysort(1,ets:select(?COLLECTION_TABLE, MS)),
+ CovLines0 =
+ lists:keysort(1, ets:select(?COLLECTION_TABLE, MS)),
+ CovLines = merge_dup_lines(CovLines0),
print_lines(Module, CovLines, InFd, OutFd, 1, HTML),
if HTML ->
@@ -2477,19 +2479,23 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) ->
{error, {file, ErlFile, Reason}}
end.
+merge_dup_lines(CovLines) ->
+ merge_dup_lines(CovLines, []).
+merge_dup_lines([{L, N}|T], [{L, NAcc}|TAcc]) ->
+ merge_dup_lines(T, [{L, NAcc + N}|TAcc]);
+merge_dup_lines([{L, N}|T], Acc) ->
+ merge_dup_lines(T, [{L, N}|Acc]);
+merge_dup_lines([], Acc) ->
+ lists:reverse(Acc).
print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
case file:read_line(InFd) of
eof ->
ignore;
- {ok,"%"++_=Line} -> %Comment line - not executed.
- ok = file:write(OutFd, [tab(),escape_lt_and_gt(Line, HTML)]),
- print_lines(Module, CovLines, InFd, OutFd, L+1, HTML);
{ok,RawLine} ->
Line = escape_lt_and_gt(RawLine,HTML),
case CovLines of
[{L,N}|CovLines1] ->
- %% N = lists:foldl(fun([Ni], Nacc) -> Nacc+Ni end, 0, Ns),
if N=:=0, HTML=:=true ->
LineNoNL = Line -- "\n",
Str = " 0",
@@ -2508,7 +2514,7 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) ->
ok = file:write(OutFd, [Str,fill3(),Line])
end,
print_lines(Module, CovLines1, InFd, OutFd, L+1, HTML);
- _ ->
+ _ -> %Including comment lines
ok = file:write(OutFd, [tab(),Line]),
print_lines(Module, CovLines, InFd, OutFd, L+1, HTML)
end
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 90e113c178..161b0105b9 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ all() ->
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
export_import, otp_5031, otp_6115,
- otp_8270, otp_10979_hanging_node],
+ otp_8270, otp_10979_hanging_node, otp_14817],
case whereis(cover_server) of
undefined ->
[coverage,StartStop ++ NoStartStop];
@@ -1574,6 +1574,30 @@ otp_10979_hanging_node(_Config) ->
ok.
+otp_14817(Config) when is_list(Config) ->
+ Test = <<"-module(otp_14817).
+ -export([a/0, b/0, c/0, d/0]).
+ a() -> ok. b() -> ok. c() -> ok.
+ d() -> ok.
+ ">>,
+ File = cc_mod(otp_14817, Test, Config),
+ ok = otp_14817:a(),
+ ok = otp_14817:b(),
+ ok = otp_14817:c(),
+ ok = otp_14817:d(),
+ {ok,[{{otp_14817,3},1},
+ {{otp_14817,3},1},
+ {{otp_14817,3},1},
+ {{otp_14817,4},1}]} =
+ cover:analyse(otp_14817, calls, line),
+ {ok, CovOut} = cover:analyse_to_file(otp_14817),
+ {ok, Bin} = file:read_file(CovOut),
+ <<"3..|",_/binary>> = string:find(Bin, "3..|"),
+ <<"1..|",_/binary>> = string:find(Bin, "1..|"),
+ ok = file:delete(File),
+ ok = file:delete(CovOut),
+ ok.
+
%% Take compiler options from beam in cover:compile_beam
compile_beam_opts(Config) when is_list(Config) ->
{ok, Cwd} = file:get_cwd(),
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index b9249ae45c..6cafbca6a7 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.11
+TOOLS_VSN = 2.11.1
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 599b5b64fd..69ea906ec0 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 1.8.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ wx crashes in otp 20.1 if empty binaries was sent down as
+ arguments.</p>
+ <p>
+ Own Id: OTP-14688</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 1.8.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 039fae322e..7da4529c98 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 1.8.2
+WX_VSN = 1.8.3
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index 1162561225..f62a8dc53d 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.3.16</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Removed all old unused files in the documentation.
+ </p>
+ <p>
+ Own Id: OTP-14475 Aux Id: ERL-409, PR-1493 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.3.15</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index 2e9c9061d9..ddff0c8894 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.3.15
+XMERL_VSN = 1.3.16